#define ATMEL_HLCDC_PWMPS_MAX          0x6
 #define ATMEL_HLCDC_PWMPS(x)           ((x) & ATMEL_HLCDC_PWMPS_MASK)
 
+struct atmel_hlcdc_pwm_errata {
+       bool slow_clk_erratum;
+       bool div1_clk_erratum;
+};
+
 struct atmel_hlcdc_pwm {
        struct pwm_chip chip;
        struct atmel_hlcdc *hlcdc;
        struct clk *cur_clk;
+       const struct atmel_hlcdc_pwm_errata *errata;
 };
 
 static inline struct atmel_hlcdc_pwm *to_atmel_hlcdc_pwm(struct pwm_chip *chip)
        u32 pwmcfg;
        int pres;
 
-       clk_freq = clk_get_rate(new_clk);
-       clk_period_ns = (u64)NSEC_PER_SEC * 256;
-       do_div(clk_period_ns, clk_freq);
+       if (!chip->errata || !chip->errata->slow_clk_erratum) {
+               clk_freq = clk_get_rate(new_clk);
+               clk_period_ns = (u64)NSEC_PER_SEC * 256;
+               do_div(clk_period_ns, clk_freq);
+       }
 
-       if (clk_period_ns > period_ns) {
+       /* Errata: cannot use slow clk on some IP revisions */
+       if ((chip->errata && chip->errata->slow_clk_erratum) ||
+           clk_period_ns > period_ns) {
                new_clk = hlcdc->sys_clk;
                clk_freq = clk_get_rate(new_clk);
                clk_period_ns = (u64)NSEC_PER_SEC * 256;
                do_div(clk_period_ns, clk_freq);
        }
 
-       for (pres = 0; pres <= ATMEL_HLCDC_PWMPS_MAX; pres++)
+       for (pres = 0; pres <= ATMEL_HLCDC_PWMPS_MAX; pres++) {
+               /* Errata: cannot divide by 1 on some IP revisions */
+               if (!pres && chip->errata && chip->errata->div1_clk_erratum)
+                       continue;
+
                if ((clk_period_ns << pres) >= period_ns)
                        break;
+       }
 
        if (pres > ATMEL_HLCDC_PWMPS_MAX)
                return -EINVAL;
        .owner = THIS_MODULE,
 };
 
+static const struct atmel_hlcdc_pwm_errata atmel_hlcdc_pwm_at91sam9x5_errata = {
+       .slow_clk_erratum = true,
+};
+
+static const struct atmel_hlcdc_pwm_errata atmel_hlcdc_pwm_sama5d3_errata = {
+       .div1_clk_erratum = true,
+};
+
+static const struct of_device_id atmel_hlcdc_dt_ids[] = {
+       {
+               .compatible = "atmel,at91sam9x5-hlcdc",
+               .data = &atmel_hlcdc_pwm_at91sam9x5_errata,
+       },
+       {
+               .compatible = "atmel,sama5d3-hlcdc",
+               .data = &atmel_hlcdc_pwm_sama5d3_errata,
+       },
+       { /* sentinel */ },
+};
+
 static int atmel_hlcdc_pwm_probe(struct platform_device *pdev)
 {
+       const struct of_device_id *match;
        struct device *dev = &pdev->dev;
        struct atmel_hlcdc_pwm *chip;
        struct atmel_hlcdc *hlcdc;
        if (ret)
                return ret;
 
+       match = of_match_node(atmel_hlcdc_dt_ids, dev->parent->of_node);
+       if (match)
+               chip->errata = match->data;
+
        chip->hlcdc = hlcdc;
        chip->chip.ops = &atmel_hlcdc_pwm_ops;
        chip->chip.dev = dev;