On Thu, Feb 21, 2019 at 06:18:47PM +0800, Wei Ni wrote: > Parse Over Current settings from DT and program them to > generate interrupts. Also enable hw throttling whenever > there are OC events. Log the OC events as debug messages. > > Signed-off-by: Wei Ni <wni@xxxxxxxxxx> I applied this series except for this specific patch which: a. does not apply clean b. does not compile. Please rebase on top of my -linus branch and resend this. remember to checkpatch and compile and boot test before sending. > --- > drivers/thermal/tegra/soctherm.c | 130 ++++++++++++++++++++++++++++++++++++--- > 1 file changed, 120 insertions(+), 10 deletions(-) > > diff --git a/drivers/thermal/tegra/soctherm.c b/drivers/thermal/tegra/soctherm.c > index b8c66368e54e..6e3f329d1ac4 100644 > --- a/drivers/thermal/tegra/soctherm.c > +++ b/drivers/thermal/tegra/soctherm.c > @@ -106,9 +106,26 @@ > #define STATS_CTL_CLR_UP 0x2 > #define STATS_CTL_EN_UP 0x1 > > +#define OC1_CFG 0x310 > +#define OC1_CFG_LONG_LATENCY_MASK BIT(6) > +#define OC1_CFG_HW_RESTORE_MASK BIT(5) > +#define OC1_CFG_PWR_GOOD_MASK_MASK BIT(4) > +#define OC1_CFG_THROTTLE_MODE_MASK (0x3 << 2) > +#define OC1_CFG_ALARM_POLARITY_MASK BIT(1) > +#define OC1_CFG_EN_THROTTLE_MASK BIT(0) > + > +#define OC1_CNT_THRESHOLD 0x314 > +#define OC1_THROTTLE_PERIOD 0x318 > +#define OC1_ALARM_COUNT 0x31c > +#define OC1_FILTER 0x320 > +#define OC1_STATS 0x3a8 > + > #define OC_INTR_STATUS 0x39c > #define OC_INTR_ENABLE 0x3a0 > #define OC_INTR_DISABLE 0x3a4 > +#define OC_STATS_CTL 0x3c4 > +#define OC_STATS_CTL_CLR_ALL 0x2 > +#define OC_STATS_CTL_EN_ALL 0x1 > > #define OC_INTR_OC1_MASK BIT(0) > #define OC_INTR_OC2_MASK BIT(1) > @@ -207,6 +224,25 @@ > #define THROT_DELAY_CTRL(throt) (THROT_DELAY_LITE + \ > (THROT_OFFSET * throt)) > > +#define ALARM_OFFSET 0x14 > +#define ALARM_CFG(throt) (OC1_CFG + \ > + (ALARM_OFFSET * (throt - THROTTLE_OC1))) > + > +#define ALARM_CNT_THRESHOLD(throt) (OC1_CNT_THRESHOLD + \ > + (ALARM_OFFSET * (throt - THROTTLE_OC1))) > + > +#define ALARM_THROTTLE_PERIOD(throt) (OC1_THROTTLE_PERIOD + \ > + (ALARM_OFFSET * (throt - THROTTLE_OC1))) > + > +#define ALARM_ALARM_COUNT(throt) (OC1_ALARM_COUNT + \ > + (ALARM_OFFSET * (throt - THROTTLE_OC1))) > + > +#define ALARM_FILTER(throt) (OC1_FILTER + \ > + (ALARM_OFFSET * (throt - THROTTLE_OC1))) > + > +#define ALARM_STATS(throt) (OC1_STATS + \ > + (4 * (throt - THROTTLE_OC1))) > + > /* get CCROC_THROT_PSKIP_xxx offset per HIGH/MED/LOW vect*/ > #define CCROC_THROT_OFFSET 0x0c > #define CCROC_THROT_PSKIP_CTRL_CPU_REG(vect) (CCROC_THROT_PSKIP_CTRL_CPU + \ > @@ -218,6 +254,9 @@ > #define THERMCTL_LVL_REGS_SIZE 0x20 > #define THERMCTL_LVL_REG(rg, lv) ((rg) + ((lv) * THERMCTL_LVL_REGS_SIZE)) > > +#define OC_THROTTLE_MODE_DISABLED 0 > +#define OC_THROTTLE_MODE_BRIEF 2 > + > static const int min_low_temp = -127000; > static const int max_high_temp = 127000; > > @@ -266,6 +305,15 @@ struct tegra_thermctl_zone { > const struct tegra_tsensor_group *sg; > }; > > +struct soctherm_oc_cfg { > + u32 active_low; > + u32 throt_period; > + u32 alarm_cnt_thresh; > + u32 alarm_filter; > + u32 mode; > + bool intr_en; > +}; > + > struct soctherm_throt_cfg { > const char *name; > unsigned int id; > @@ -273,6 +321,7 @@ struct soctherm_throt_cfg { > u8 cpu_throt_level; > u32 cpu_throt_depth; > u32 gpu_throt_level; > + struct soctherm_oc_cfg oc_cfg; > struct thermal_cooling_device *cdev; > bool init; > }; > @@ -715,7 +764,7 @@ static int tegra_soctherm_set_hwtrips(struct device *dev, > return 0; > } > > - for (i = 0; i < THROTTLE_SIZE; i++) { > + for (i = 0; i < THROTTLE_OC1; i++) { > struct thermal_cooling_device *cdev; > > if (!ts->throt_cfgs[i].init) > @@ -1537,6 +1586,32 @@ static int soctherm_thermtrips_parse(struct platform_device *pdev) > return 0; > } > > +static void soctherm_oc_cfg_parse(struct device *dev, > + struct device_node *np_oc, > + struct soctherm_throt_cfg *stc) > +{ > + u32 val; > + > + if (of_property_read_bool(np_oc, "nvidia,polarity-active-low")) > + stc->oc_cfg.active_low = 1; > + else > + stc->oc_cfg.active_low = 0; > + > + if (!of_property_read_u32(np_oc, "nvidia,count-threshold", &val)) { > + stc->oc_cfg.intr_en = 1; > + stc->oc_cfg.alarm_cnt_thresh = val; > + } > + > + if (!of_property_read_u32(np_oc, "nvidia,throttle-period-us", &val)) > + stc->oc_cfg.throt_period = val; > + > + if (!of_property_read_u32(np_oc, "nvidia,alarm-filter", &val)) > + stc->oc_cfg.alarm_filter = val; > + > + /* BRIEF throttling by default, do not support STICKY */ > + stc->oc_cfg.mode = OC_THROTTLE_MODE_BRIEF; > +} > + > static int soctherm_throt_cfg_parse(struct device *dev, > struct device_node *np, > struct soctherm_throt_cfg *stc) > @@ -1619,24 +1694,34 @@ static void soctherm_init_hw_throt_cdev(struct platform_device *pdev) > continue; > } > > + if (stc->init) { > + dev_err(dev, "throttle-cfg: %s: redefined!\n", name); > + of_node_put(np_stcc); > + break; > + } > > err = soctherm_throt_cfg_parse(dev, np_stcc, stc); > if (err) > continue; > > - tcd = thermal_of_cooling_device_register(np_stcc, > + if (stc->id >= THROTTLE_OC1) { > + soctherm_oc_cfg_parse(dev, np_stcc, stc); > + stc->init = true; > + } else { > + > + tcd = thermal_of_cooling_device_register(np_stcc, > (char *)name, ts, > &throt_cooling_ops); > - of_node_put(np_stcc); > - if (IS_ERR_OR_NULL(tcd)) { > - dev_err(dev, > - "throttle-cfg: %s: failed to register cooling device\n", > - name); > - continue; > + if (IS_ERR_OR_NULL(tcd)) { > + dev_err(dev, > + "throttle-cfg: %s: failed to register cooling device\n", > + name); > + continue; > + } > + stc->cdev = tcd; > + stc->init = true; > } > > - stc->cdev = tcd; > - stc->init = true; > } > > of_node_put(np_stc); > @@ -1787,6 +1872,28 @@ static void throttlectl_gpu_level_select(struct tegra_soctherm *ts, > writel(r, ts->regs + THROT_PSKIP_CTRL(throt, THROTTLE_DEV_GPU)); > } > > +static int soctherm_oc_cfg_program(struct tegra_soctherm *ts, > + enum soctherm_throttle_id throt) > +{ > + u32 r; > + struct soctherm_oc_cfg *oc = &ts->throt_cfgs[throt].oc_cfg; > + > + if (oc->mode == OC_THROTTLE_MODE_DISABLED) > + return -EINVAL; > + > + r = REG_SET_MASK(0, OC1_CFG_HW_RESTORE_MASK, 1); > + r = REG_SET_MASK(r, OC1_CFG_THROTTLE_MODE_MASK, oc->mode); > + r = REG_SET_MASK(r, OC1_CFG_ALARM_POLARITY_MASK, oc->active_low); > + r = REG_SET_MASK(r, OC1_CFG_EN_THROTTLE_MASK, 1); > + writel(r, ts->regs + ALARM_CFG(throt)); > + writel(oc->throt_period, ts->regs + ALARM_THROTTLE_PERIOD(throt)); > + writel(oc->alarm_cnt_thresh, ts->regs + ALARM_CNT_THRESHOLD(throt)); > + writel(oc->alarm_filter, ts->regs + ALARM_FILTER(throt)); > + soctherm_oc_intr_enable(ts, throt, oc->intr_en); > + > + return 0; > +} > + > /** > * soctherm_throttle_program() - programs pulse skippers' configuration > * @throt: the LIGHT/HEAVY of the throttle event id. > @@ -1803,6 +1910,9 @@ static void soctherm_throttle_program(struct tegra_soctherm *ts, > if (!stc.init) > return; > > + if ((throt >= THROTTLE_OC1) && (soctherm_oc_cfg_program(ts, throt))) > + return; > + > /* Setup PSKIP parameters */ > if (ts->soc->use_ccroc) > throttlectl_cpu_level_select(ts, throt); > -- > 2.7.4 >