@@ -65,11 +65,13 @@ struct mtk_pwm_platform_data {
* @chip: linux PWM chip representation
* @regs: base address of PWM chip
* @clks: list of clocks
+ * @clk_freq: the fix clock frequency of legacy MIPS SoC
*/
struct mtk_pwm_chip {
struct pwm_chip chip;
void __iomem *regs;
struct clk *clks[MTK_CLK_MAX];
+ unsigned int clk_freq;
const struct mtk_pwm_platform_data *soc;
};
@@ -141,19 +143,27 @@ static int mtk_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
int duty_ns, int period_ns)
{
struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip);
- struct clk *clk = pc->clks[MTK_CLK_PWM1 + pwm->hwpwm];
+ unsigned int clk_freq;
u32 clkdiv = 0, cnt_period, cnt_duty, reg_width = PWMDWIDTH,
reg_thres = PWMTHRES;
u64 resolution;
int ret;
+ if (pc->soc->has_clks) {
+ struct clk *clk = pc->clks[MTK_CLK_PWM1 + pwm->hwpwm];
+
+ clk_freq = clk_get_rate(clk);
+ } else {
+ clk_freq = pc->clk_freq;
+ }
+
ret = mtk_pwm_clk_enable(chip, pwm);
if (ret < 0)
return ret;
/* Using resolution in picosecond gets accuracy higher */
resolution = (u64)NSEC_PER_SEC * 1000;
- do_div(resolution, clk_get_rate(clk));
+ do_div(resolution, clk_freq);
cnt_period = DIV_ROUND_CLOSEST_ULL((u64)period_ns * 1000, resolution);
while (cnt_period > 8191) {
@@ -262,13 +272,26 @@ static int mtk_pwm_probe(struct platform_device *pdev)
npwms = MTK_CLK_MAX - 2;
}
- for (i = 0; i < npwms + 2 && pc->soc->has_clks; i++) {
- pc->clks[i] = devm_clk_get(&pdev->dev, mtk_pwm_clk_name[i]);
- if (IS_ERR(pc->clks[i])) {
- dev_err(&pdev->dev, "clock: %s fail: %ld\n",
- mtk_pwm_clk_name[i], PTR_ERR(pc->clks[i]));
- return PTR_ERR(pc->clks[i]);
+ if (pc->soc->has_clks) {
+ for (i = 0; i < npwms + 2 ; i++) {
+ pc->clks[i] = devm_clk_get(&pdev->dev,
+ mtk_pwm_clk_name[i]);
+ if (IS_ERR(pc->clks[i])) {
+ dev_err(&pdev->dev, "clock: %s fail: %ld\n",
+ mtk_pwm_clk_name[i],
+ PTR_ERR(pc->clks[i]));
+ return PTR_ERR(pc->clks[i]);
+ }
+ }
+ } else {
+ unsigned int clk_freq;
+
+ ret = of_property_read_u32(np, "clock-frequency", &clk_freq);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to get clock_frequency\n");
+ return ret;
}
+ pc->clk_freq = clk_freq;
}
platform_set_drvdata(pdev, pc);