Skip to content

Commit 1969d9d

Browse files
ykanekoEduardo Valentin
authored andcommitted
thermal: rcar_thermal: add r8a77995 support
Add support for R-Car D3 (r8a77995) thermal sensor. Signed-off-by: Yoshihiro Kaneko <ykaneko0929@gmail.com> Tested-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com> Reviewed-by: Simon Horman <horms+renesas@verge.net.au> Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
1 parent 31db453 commit 1969d9d

File tree

1 file changed

+126
-32
lines changed

1 file changed

+126
-32
lines changed

drivers/thermal/rcar_thermal.c

Lines changed: 126 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,47 @@ struct rcar_thermal_common {
5858
spinlock_t lock;
5959
};
6060

61+
struct rcar_thermal_chip {
62+
unsigned int use_of_thermal : 1;
63+
unsigned int has_filonoff : 1;
64+
unsigned int irq_per_ch : 1;
65+
unsigned int needs_suspend_resume : 1;
66+
unsigned int nirqs;
67+
};
68+
69+
static const struct rcar_thermal_chip rcar_thermal = {
70+
.use_of_thermal = 0,
71+
.has_filonoff = 1,
72+
.irq_per_ch = 0,
73+
.needs_suspend_resume = 0,
74+
.nirqs = 1,
75+
};
76+
77+
static const struct rcar_thermal_chip rcar_gen2_thermal = {
78+
.use_of_thermal = 1,
79+
.has_filonoff = 1,
80+
.irq_per_ch = 0,
81+
.needs_suspend_resume = 0,
82+
.nirqs = 1,
83+
};
84+
85+
static const struct rcar_thermal_chip rcar_gen3_thermal = {
86+
.use_of_thermal = 1,
87+
.has_filonoff = 0,
88+
.irq_per_ch = 1,
89+
.needs_suspend_resume = 1,
90+
/*
91+
* The Gen3 chip has 3 interrupts, but this driver uses only 2
92+
* interrupts to detect a temperature change, rise or fall.
93+
*/
94+
.nirqs = 2,
95+
};
96+
6197
struct rcar_thermal_priv {
6298
void __iomem *base;
6399
struct rcar_thermal_common *common;
64100
struct thermal_zone_device *zone;
101+
const struct rcar_thermal_chip *chip;
65102
struct delayed_work work;
66103
struct mutex lock;
67104
struct list_head list;
@@ -77,13 +114,20 @@ struct rcar_thermal_priv {
77114
#define rcar_priv_to_dev(priv) ((priv)->common->dev)
78115
#define rcar_has_irq_support(priv) ((priv)->common->base)
79116
#define rcar_id_to_shift(priv) ((priv)->id * 8)
80-
#define rcar_of_data(dev) ((unsigned long)of_device_get_match_data(dev))
81-
#define rcar_use_of_thermal(dev) (rcar_of_data(dev) == USE_OF_THERMAL)
82117

83-
#define USE_OF_THERMAL 1
84118
static const struct of_device_id rcar_thermal_dt_ids[] = {
85-
{ .compatible = "renesas,rcar-thermal", },
86-
{ .compatible = "renesas,rcar-gen2-thermal", .data = (void *)USE_OF_THERMAL },
119+
{
120+
.compatible = "renesas,rcar-thermal",
121+
.data = &rcar_thermal,
122+
},
123+
{
124+
.compatible = "renesas,rcar-gen2-thermal",
125+
.data = &rcar_gen2_thermal,
126+
},
127+
{
128+
.compatible = "renesas,thermal-r8a77995",
129+
.data = &rcar_gen3_thermal,
130+
},
87131
{},
88132
};
89133
MODULE_DEVICE_TABLE(of, rcar_thermal_dt_ids);
@@ -190,7 +234,8 @@ static int rcar_thermal_update_temp(struct rcar_thermal_priv *priv)
190234
* enable IRQ
191235
*/
192236
if (rcar_has_irq_support(priv)) {
193-
rcar_thermal_write(priv, FILONOFF, 0);
237+
if (priv->chip->has_filonoff)
238+
rcar_thermal_write(priv, FILONOFF, 0);
194239

195240
/* enable Rising/Falling edge interrupt */
196241
rcar_thermal_write(priv, POSNEG, 0x1);
@@ -420,7 +465,7 @@ static int rcar_thermal_remove(struct platform_device *pdev)
420465

421466
rcar_thermal_for_each_priv(priv, common) {
422467
rcar_thermal_irq_disable(priv);
423-
if (rcar_use_of_thermal(dev))
468+
if (priv->chip->use_of_thermal)
424469
thermal_remove_hwmon_sysfs(priv->zone);
425470
else
426471
thermal_zone_device_unregister(priv->zone);
@@ -438,6 +483,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
438483
struct rcar_thermal_priv *priv;
439484
struct device *dev = &pdev->dev;
440485
struct resource *res, *irq;
486+
const struct rcar_thermal_chip *chip = of_device_get_match_data(dev);
441487
int mres = 0;
442488
int i;
443489
int ret = -ENODEV;
@@ -457,19 +503,35 @@ static int rcar_thermal_probe(struct platform_device *pdev)
457503
pm_runtime_enable(dev);
458504
pm_runtime_get_sync(dev);
459505

460-
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
461-
if (irq) {
462-
/*
463-
* platform has IRQ support.
464-
* Then, driver uses common registers
465-
* rcar_has_irq_support() will be enabled
466-
*/
467-
res = platform_get_resource(pdev, IORESOURCE_MEM, mres++);
468-
common->base = devm_ioremap_resource(dev, res);
469-
if (IS_ERR(common->base))
470-
return PTR_ERR(common->base);
506+
for (i = 0; i < chip->nirqs; i++) {
507+
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
508+
if (!irq)
509+
continue;
510+
if (!common->base) {
511+
/*
512+
* platform has IRQ support.
513+
* Then, driver uses common registers
514+
* rcar_has_irq_support() will be enabled
515+
*/
516+
res = platform_get_resource(pdev, IORESOURCE_MEM,
517+
mres++);
518+
common->base = devm_ioremap_resource(dev, res);
519+
if (IS_ERR(common->base))
520+
return PTR_ERR(common->base);
521+
522+
idle = 0; /* polling delay is not needed */
523+
}
471524

472-
idle = 0; /* polling delay is not needed */
525+
ret = devm_request_irq(dev, irq->start, rcar_thermal_irq,
526+
IRQF_SHARED, dev_name(dev), common);
527+
if (ret) {
528+
dev_err(dev, "irq request failed\n ");
529+
goto error_unregister;
530+
}
531+
532+
/* update ENR bits */
533+
if (chip->irq_per_ch)
534+
enr_bits |= 1 << i;
473535
}
474536

475537
for (i = 0;; i++) {
@@ -491,14 +553,15 @@ static int rcar_thermal_probe(struct platform_device *pdev)
491553

492554
priv->common = common;
493555
priv->id = i;
556+
priv->chip = chip;
494557
mutex_init(&priv->lock);
495558
INIT_LIST_HEAD(&priv->list);
496559
INIT_DELAYED_WORK(&priv->work, rcar_thermal_work);
497560
ret = rcar_thermal_update_temp(priv);
498561
if (ret < 0)
499562
goto error_unregister;
500563

501-
if (rcar_use_of_thermal(dev))
564+
if (chip->use_of_thermal)
502565
priv->zone = devm_thermal_zone_of_sensor_register(
503566
dev, i, priv,
504567
&rcar_thermal_zone_of_ops);
@@ -515,7 +578,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
515578
goto error_unregister;
516579
}
517580

518-
if (rcar_use_of_thermal(dev)) {
581+
if (chip->use_of_thermal) {
519582
/*
520583
* thermal_zone doesn't enable hwmon as default,
521584
* but, enable it here to keep compatible
@@ -531,20 +594,12 @@ static int rcar_thermal_probe(struct platform_device *pdev)
531594
list_move_tail(&priv->list, &common->head);
532595

533596
/* update ENR bits */
534-
enr_bits |= 3 << (i * 8);
597+
if (!chip->irq_per_ch)
598+
enr_bits |= 3 << (i * 8);
535599
}
536600

537-
/* enable temperature comparation */
538-
if (irq) {
539-
ret = devm_request_irq(dev, irq->start, rcar_thermal_irq, 0,
540-
dev_name(dev), common);
541-
if (ret) {
542-
dev_err(dev, "irq request failed\n ");
543-
goto error_unregister;
544-
}
545-
601+
if (enr_bits)
546602
rcar_thermal_common_write(common, ENR, enr_bits);
547-
}
548603

549604
dev_info(dev, "%d sensor probed\n", i);
550605

@@ -556,9 +611,48 @@ static int rcar_thermal_probe(struct platform_device *pdev)
556611
return ret;
557612
}
558613

614+
#ifdef CONFIG_PM_SLEEP
615+
static int rcar_thermal_suspend(struct device *dev)
616+
{
617+
struct rcar_thermal_common *common = dev_get_drvdata(dev);
618+
struct rcar_thermal_priv *priv = list_first_entry(&common->head,
619+
typeof(*priv), list);
620+
621+
if (priv->chip->needs_suspend_resume) {
622+
rcar_thermal_common_write(common, ENR, 0);
623+
rcar_thermal_irq_disable(priv);
624+
rcar_thermal_bset(priv, THSCR, CPCTL, 0);
625+
}
626+
627+
return 0;
628+
}
629+
630+
static int rcar_thermal_resume(struct device *dev)
631+
{
632+
struct rcar_thermal_common *common = dev_get_drvdata(dev);
633+
struct rcar_thermal_priv *priv = list_first_entry(&common->head,
634+
typeof(*priv), list);
635+
int ret;
636+
637+
if (priv->chip->needs_suspend_resume) {
638+
ret = rcar_thermal_update_temp(priv);
639+
if (ret < 0)
640+
return ret;
641+
rcar_thermal_irq_enable(priv);
642+
rcar_thermal_common_write(common, ENR, 0x03);
643+
}
644+
645+
return 0;
646+
}
647+
#endif
648+
649+
static SIMPLE_DEV_PM_OPS(rcar_thermal_pm_ops, rcar_thermal_suspend,
650+
rcar_thermal_resume);
651+
559652
static struct platform_driver rcar_thermal_driver = {
560653
.driver = {
561654
.name = "rcar_thermal",
655+
.pm = &rcar_thermal_pm_ops,
562656
.of_match_table = rcar_thermal_dt_ids,
563657
},
564658
.probe = rcar_thermal_probe,

0 commit comments

Comments
 (0)