Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
0002 /*
0003  * PWM controller driver for Amlogic Meson SoCs.
0004  *
0005  * This PWM is only a set of Gates, Dividers and Counters:
0006  * PWM output is achieved by calculating a clock that permits calculating
0007  * two periods (low and high). The counter then has to be set to switch after
0008  * N cycles for the first half period.
0009  * The hardware has no "polarity" setting. This driver reverses the period
0010  * cycles (the low length is inverted with the high length) for
0011  * PWM_POLARITY_INVERSED. This means that .get_state cannot read the polarity
0012  * from the hardware.
0013  * Setting the duty cycle will disable and re-enable the PWM output.
0014  * Disabling the PWM stops the output immediately (without waiting for the
0015  * current period to complete first).
0016  *
0017  * The public S912 (GXM) datasheet contains some documentation for this PWM
0018  * controller starting on page 543:
0019  * https://dl.khadas.com/Hardware/VIM2/Datasheet/S912_Datasheet_V0.220170314publicversion-Wesion.pdf
0020  * An updated version of this IP block is found in S922X (G12B) SoCs. The
0021  * datasheet contains the description for this IP block revision starting at
0022  * page 1084:
0023  * https://dn.odroid.com/S922X/ODROID-N2/Datasheet/S922X_Public_Datasheet_V0.2.pdf
0024  *
0025  * Copyright (c) 2016 BayLibre, SAS.
0026  * Author: Neil Armstrong <narmstrong@baylibre.com>
0027  * Copyright (C) 2014 Amlogic, Inc.
0028  */
0029 
0030 #include <linux/bitfield.h>
0031 #include <linux/bits.h>
0032 #include <linux/clk.h>
0033 #include <linux/clk-provider.h>
0034 #include <linux/err.h>
0035 #include <linux/io.h>
0036 #include <linux/kernel.h>
0037 #include <linux/math64.h>
0038 #include <linux/module.h>
0039 #include <linux/of.h>
0040 #include <linux/of_device.h>
0041 #include <linux/platform_device.h>
0042 #include <linux/pwm.h>
0043 #include <linux/slab.h>
0044 #include <linux/spinlock.h>
0045 
0046 #define REG_PWM_A       0x0
0047 #define REG_PWM_B       0x4
0048 #define PWM_LOW_MASK        GENMASK(15, 0)
0049 #define PWM_HIGH_MASK       GENMASK(31, 16)
0050 
0051 #define REG_MISC_AB     0x8
0052 #define MISC_B_CLK_EN       BIT(23)
0053 #define MISC_A_CLK_EN       BIT(15)
0054 #define MISC_CLK_DIV_MASK   0x7f
0055 #define MISC_B_CLK_DIV_SHIFT    16
0056 #define MISC_A_CLK_DIV_SHIFT    8
0057 #define MISC_B_CLK_SEL_SHIFT    6
0058 #define MISC_A_CLK_SEL_SHIFT    4
0059 #define MISC_CLK_SEL_MASK   0x3
0060 #define MISC_B_EN       BIT(1)
0061 #define MISC_A_EN       BIT(0)
0062 
0063 #define MESON_NUM_PWMS      2
0064 
0065 static struct meson_pwm_channel_data {
0066     u8      reg_offset;
0067     u8      clk_sel_shift;
0068     u8      clk_div_shift;
0069     u32     clk_en_mask;
0070     u32     pwm_en_mask;
0071 } meson_pwm_per_channel_data[MESON_NUM_PWMS] = {
0072     {
0073         .reg_offset = REG_PWM_A,
0074         .clk_sel_shift  = MISC_A_CLK_SEL_SHIFT,
0075         .clk_div_shift  = MISC_A_CLK_DIV_SHIFT,
0076         .clk_en_mask    = MISC_A_CLK_EN,
0077         .pwm_en_mask    = MISC_A_EN,
0078     },
0079     {
0080         .reg_offset = REG_PWM_B,
0081         .clk_sel_shift  = MISC_B_CLK_SEL_SHIFT,
0082         .clk_div_shift  = MISC_B_CLK_DIV_SHIFT,
0083         .clk_en_mask    = MISC_B_CLK_EN,
0084         .pwm_en_mask    = MISC_B_EN,
0085     }
0086 };
0087 
0088 struct meson_pwm_channel {
0089     unsigned int hi;
0090     unsigned int lo;
0091     u8 pre_div;
0092 
0093     struct clk *clk_parent;
0094     struct clk_mux mux;
0095     struct clk *clk;
0096 };
0097 
0098 struct meson_pwm_data {
0099     const char * const *parent_names;
0100     unsigned int num_parents;
0101 };
0102 
0103 struct meson_pwm {
0104     struct pwm_chip chip;
0105     const struct meson_pwm_data *data;
0106     struct meson_pwm_channel channels[MESON_NUM_PWMS];
0107     void __iomem *base;
0108     /*
0109      * Protects register (write) access to the REG_MISC_AB register
0110      * that is shared between the two PWMs.
0111      */
0112     spinlock_t lock;
0113 };
0114 
0115 static inline struct meson_pwm *to_meson_pwm(struct pwm_chip *chip)
0116 {
0117     return container_of(chip, struct meson_pwm, chip);
0118 }
0119 
0120 static int meson_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
0121 {
0122     struct meson_pwm *meson = to_meson_pwm(chip);
0123     struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm];
0124     struct device *dev = chip->dev;
0125     int err;
0126 
0127     if (channel->clk_parent) {
0128         err = clk_set_parent(channel->clk, channel->clk_parent);
0129         if (err < 0) {
0130             dev_err(dev, "failed to set parent %s for %s: %d\n",
0131                 __clk_get_name(channel->clk_parent),
0132                 __clk_get_name(channel->clk), err);
0133             return err;
0134         }
0135     }
0136 
0137     err = clk_prepare_enable(channel->clk);
0138     if (err < 0) {
0139         dev_err(dev, "failed to enable clock %s: %d\n",
0140             __clk_get_name(channel->clk), err);
0141         return err;
0142     }
0143 
0144     return 0;
0145 }
0146 
0147 static void meson_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
0148 {
0149     struct meson_pwm *meson = to_meson_pwm(chip);
0150     struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm];
0151 
0152     clk_disable_unprepare(channel->clk);
0153 }
0154 
0155 static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm,
0156               const struct pwm_state *state)
0157 {
0158     struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm];
0159     unsigned int duty, period, pre_div, cnt, duty_cnt;
0160     unsigned long fin_freq;
0161 
0162     duty = state->duty_cycle;
0163     period = state->period;
0164 
0165     if (state->polarity == PWM_POLARITY_INVERSED)
0166         duty = period - duty;
0167 
0168     fin_freq = clk_get_rate(channel->clk);
0169     if (fin_freq == 0) {
0170         dev_err(meson->chip.dev, "invalid source clock frequency\n");
0171         return -EINVAL;
0172     }
0173 
0174     dev_dbg(meson->chip.dev, "fin_freq: %lu Hz\n", fin_freq);
0175 
0176     pre_div = div64_u64(fin_freq * (u64)period, NSEC_PER_SEC * 0xffffLL);
0177     if (pre_div > MISC_CLK_DIV_MASK) {
0178         dev_err(meson->chip.dev, "unable to get period pre_div\n");
0179         return -EINVAL;
0180     }
0181 
0182     cnt = div64_u64(fin_freq * (u64)period, NSEC_PER_SEC * (pre_div + 1));
0183     if (cnt > 0xffff) {
0184         dev_err(meson->chip.dev, "unable to get period cnt\n");
0185         return -EINVAL;
0186     }
0187 
0188     dev_dbg(meson->chip.dev, "period=%u pre_div=%u cnt=%u\n", period,
0189         pre_div, cnt);
0190 
0191     if (duty == period) {
0192         channel->pre_div = pre_div;
0193         channel->hi = cnt;
0194         channel->lo = 0;
0195     } else if (duty == 0) {
0196         channel->pre_div = pre_div;
0197         channel->hi = 0;
0198         channel->lo = cnt;
0199     } else {
0200         /* Then check is we can have the duty with the same pre_div */
0201         duty_cnt = div64_u64(fin_freq * (u64)duty,
0202                      NSEC_PER_SEC * (pre_div + 1));
0203         if (duty_cnt > 0xffff) {
0204             dev_err(meson->chip.dev, "unable to get duty cycle\n");
0205             return -EINVAL;
0206         }
0207 
0208         dev_dbg(meson->chip.dev, "duty=%u pre_div=%u duty_cnt=%u\n",
0209             duty, pre_div, duty_cnt);
0210 
0211         channel->pre_div = pre_div;
0212         channel->hi = duty_cnt;
0213         channel->lo = cnt - duty_cnt;
0214     }
0215 
0216     return 0;
0217 }
0218 
0219 static void meson_pwm_enable(struct meson_pwm *meson, struct pwm_device *pwm)
0220 {
0221     struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm];
0222     struct meson_pwm_channel_data *channel_data;
0223     unsigned long flags;
0224     u32 value;
0225 
0226     channel_data = &meson_pwm_per_channel_data[pwm->hwpwm];
0227 
0228     spin_lock_irqsave(&meson->lock, flags);
0229 
0230     value = readl(meson->base + REG_MISC_AB);
0231     value &= ~(MISC_CLK_DIV_MASK << channel_data->clk_div_shift);
0232     value |= channel->pre_div << channel_data->clk_div_shift;
0233     value |= channel_data->clk_en_mask;
0234     writel(value, meson->base + REG_MISC_AB);
0235 
0236     value = FIELD_PREP(PWM_HIGH_MASK, channel->hi) |
0237         FIELD_PREP(PWM_LOW_MASK, channel->lo);
0238     writel(value, meson->base + channel_data->reg_offset);
0239 
0240     value = readl(meson->base + REG_MISC_AB);
0241     value |= channel_data->pwm_en_mask;
0242     writel(value, meson->base + REG_MISC_AB);
0243 
0244     spin_unlock_irqrestore(&meson->lock, flags);
0245 }
0246 
0247 static void meson_pwm_disable(struct meson_pwm *meson, struct pwm_device *pwm)
0248 {
0249     unsigned long flags;
0250     u32 value;
0251 
0252     spin_lock_irqsave(&meson->lock, flags);
0253 
0254     value = readl(meson->base + REG_MISC_AB);
0255     value &= ~meson_pwm_per_channel_data[pwm->hwpwm].pwm_en_mask;
0256     writel(value, meson->base + REG_MISC_AB);
0257 
0258     spin_unlock_irqrestore(&meson->lock, flags);
0259 }
0260 
0261 static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
0262                const struct pwm_state *state)
0263 {
0264     struct meson_pwm *meson = to_meson_pwm(chip);
0265     struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm];
0266     int err = 0;
0267 
0268     if (!state->enabled) {
0269         if (state->polarity == PWM_POLARITY_INVERSED) {
0270             /*
0271              * This IP block revision doesn't have an "always high"
0272              * setting which we can use for "inverted disabled".
0273              * Instead we achieve this using the same settings
0274              * that we use a pre_div of 0 (to get the shortest
0275              * possible duration for one "count") and
0276              * "period == duty_cycle". This results in a signal
0277              * which is LOW for one "count", while being HIGH for
0278              * the rest of the (so the signal is HIGH for slightly
0279              * less than 100% of the period, but this is the best
0280              * we can achieve).
0281              */
0282             channel->pre_div = 0;
0283             channel->hi = ~0;
0284             channel->lo = 0;
0285 
0286             meson_pwm_enable(meson, pwm);
0287         } else {
0288             meson_pwm_disable(meson, pwm);
0289         }
0290     } else {
0291         err = meson_pwm_calc(meson, pwm, state);
0292         if (err < 0)
0293             return err;
0294 
0295         meson_pwm_enable(meson, pwm);
0296     }
0297 
0298     return 0;
0299 }
0300 
0301 static unsigned int meson_pwm_cnt_to_ns(struct pwm_chip *chip,
0302                     struct pwm_device *pwm, u32 cnt)
0303 {
0304     struct meson_pwm *meson = to_meson_pwm(chip);
0305     struct meson_pwm_channel *channel;
0306     unsigned long fin_freq;
0307     u32 fin_ns;
0308 
0309     /* to_meson_pwm() can only be used after .get_state() is called */
0310     channel = &meson->channels[pwm->hwpwm];
0311 
0312     fin_freq = clk_get_rate(channel->clk);
0313     if (fin_freq == 0)
0314         return 0;
0315 
0316     fin_ns = div_u64(NSEC_PER_SEC, fin_freq);
0317 
0318     return cnt * fin_ns * (channel->pre_div + 1);
0319 }
0320 
0321 static void meson_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
0322                 struct pwm_state *state)
0323 {
0324     struct meson_pwm *meson = to_meson_pwm(chip);
0325     struct meson_pwm_channel_data *channel_data;
0326     struct meson_pwm_channel *channel;
0327     u32 value, tmp;
0328 
0329     if (!state)
0330         return;
0331 
0332     channel = &meson->channels[pwm->hwpwm];
0333     channel_data = &meson_pwm_per_channel_data[pwm->hwpwm];
0334 
0335     value = readl(meson->base + REG_MISC_AB);
0336 
0337     tmp = channel_data->pwm_en_mask | channel_data->clk_en_mask;
0338     state->enabled = (value & tmp) == tmp;
0339 
0340     tmp = value >> channel_data->clk_div_shift;
0341     channel->pre_div = FIELD_GET(MISC_CLK_DIV_MASK, tmp);
0342 
0343     value = readl(meson->base + channel_data->reg_offset);
0344 
0345     channel->lo = FIELD_GET(PWM_LOW_MASK, value);
0346     channel->hi = FIELD_GET(PWM_HIGH_MASK, value);
0347 
0348     if (channel->lo == 0) {
0349         state->period = meson_pwm_cnt_to_ns(chip, pwm, channel->hi);
0350         state->duty_cycle = state->period;
0351     } else if (channel->lo >= channel->hi) {
0352         state->period = meson_pwm_cnt_to_ns(chip, pwm,
0353                             channel->lo + channel->hi);
0354         state->duty_cycle = meson_pwm_cnt_to_ns(chip, pwm,
0355                             channel->hi);
0356     } else {
0357         state->period = 0;
0358         state->duty_cycle = 0;
0359     }
0360 }
0361 
0362 static const struct pwm_ops meson_pwm_ops = {
0363     .request = meson_pwm_request,
0364     .free = meson_pwm_free,
0365     .apply = meson_pwm_apply,
0366     .get_state = meson_pwm_get_state,
0367     .owner = THIS_MODULE,
0368 };
0369 
0370 static const char * const pwm_meson8b_parent_names[] = {
0371     "xtal", "vid_pll", "fclk_div4", "fclk_div3"
0372 };
0373 
0374 static const struct meson_pwm_data pwm_meson8b_data = {
0375     .parent_names = pwm_meson8b_parent_names,
0376     .num_parents = ARRAY_SIZE(pwm_meson8b_parent_names),
0377 };
0378 
0379 static const char * const pwm_gxbb_parent_names[] = {
0380     "xtal", "hdmi_pll", "fclk_div4", "fclk_div3"
0381 };
0382 
0383 static const struct meson_pwm_data pwm_gxbb_data = {
0384     .parent_names = pwm_gxbb_parent_names,
0385     .num_parents = ARRAY_SIZE(pwm_gxbb_parent_names),
0386 };
0387 
0388 /*
0389  * Only the 2 first inputs of the GXBB AO PWMs are valid
0390  * The last 2 are grounded
0391  */
0392 static const char * const pwm_gxbb_ao_parent_names[] = {
0393     "xtal", "clk81"
0394 };
0395 
0396 static const struct meson_pwm_data pwm_gxbb_ao_data = {
0397     .parent_names = pwm_gxbb_ao_parent_names,
0398     .num_parents = ARRAY_SIZE(pwm_gxbb_ao_parent_names),
0399 };
0400 
0401 static const char * const pwm_axg_ee_parent_names[] = {
0402     "xtal", "fclk_div5", "fclk_div4", "fclk_div3"
0403 };
0404 
0405 static const struct meson_pwm_data pwm_axg_ee_data = {
0406     .parent_names = pwm_axg_ee_parent_names,
0407     .num_parents = ARRAY_SIZE(pwm_axg_ee_parent_names),
0408 };
0409 
0410 static const char * const pwm_axg_ao_parent_names[] = {
0411     "aoclk81", "xtal", "fclk_div4", "fclk_div5"
0412 };
0413 
0414 static const struct meson_pwm_data pwm_axg_ao_data = {
0415     .parent_names = pwm_axg_ao_parent_names,
0416     .num_parents = ARRAY_SIZE(pwm_axg_ao_parent_names),
0417 };
0418 
0419 static const char * const pwm_g12a_ao_ab_parent_names[] = {
0420     "xtal", "aoclk81", "fclk_div4", "fclk_div5"
0421 };
0422 
0423 static const struct meson_pwm_data pwm_g12a_ao_ab_data = {
0424     .parent_names = pwm_g12a_ao_ab_parent_names,
0425     .num_parents = ARRAY_SIZE(pwm_g12a_ao_ab_parent_names),
0426 };
0427 
0428 static const char * const pwm_g12a_ao_cd_parent_names[] = {
0429     "xtal", "aoclk81",
0430 };
0431 
0432 static const struct meson_pwm_data pwm_g12a_ao_cd_data = {
0433     .parent_names = pwm_g12a_ao_cd_parent_names,
0434     .num_parents = ARRAY_SIZE(pwm_g12a_ao_cd_parent_names),
0435 };
0436 
0437 static const char * const pwm_g12a_ee_parent_names[] = {
0438     "xtal", "hdmi_pll", "fclk_div4", "fclk_div3"
0439 };
0440 
0441 static const struct meson_pwm_data pwm_g12a_ee_data = {
0442     .parent_names = pwm_g12a_ee_parent_names,
0443     .num_parents = ARRAY_SIZE(pwm_g12a_ee_parent_names),
0444 };
0445 
0446 static const struct of_device_id meson_pwm_matches[] = {
0447     {
0448         .compatible = "amlogic,meson8b-pwm",
0449         .data = &pwm_meson8b_data
0450     },
0451     {
0452         .compatible = "amlogic,meson-gxbb-pwm",
0453         .data = &pwm_gxbb_data
0454     },
0455     {
0456         .compatible = "amlogic,meson-gxbb-ao-pwm",
0457         .data = &pwm_gxbb_ao_data
0458     },
0459     {
0460         .compatible = "amlogic,meson-axg-ee-pwm",
0461         .data = &pwm_axg_ee_data
0462     },
0463     {
0464         .compatible = "amlogic,meson-axg-ao-pwm",
0465         .data = &pwm_axg_ao_data
0466     },
0467     {
0468         .compatible = "amlogic,meson-g12a-ee-pwm",
0469         .data = &pwm_g12a_ee_data
0470     },
0471     {
0472         .compatible = "amlogic,meson-g12a-ao-pwm-ab",
0473         .data = &pwm_g12a_ao_ab_data
0474     },
0475     {
0476         .compatible = "amlogic,meson-g12a-ao-pwm-cd",
0477         .data = &pwm_g12a_ao_cd_data
0478     },
0479     {},
0480 };
0481 MODULE_DEVICE_TABLE(of, meson_pwm_matches);
0482 
0483 static int meson_pwm_init_channels(struct meson_pwm *meson)
0484 {
0485     struct device *dev = meson->chip.dev;
0486     struct clk_init_data init;
0487     unsigned int i;
0488     char name[255];
0489     int err;
0490 
0491     for (i = 0; i < meson->chip.npwm; i++) {
0492         struct meson_pwm_channel *channel = &meson->channels[i];
0493 
0494         snprintf(name, sizeof(name), "%s#mux%u", dev_name(dev), i);
0495 
0496         init.name = name;
0497         init.ops = &clk_mux_ops;
0498         init.flags = 0;
0499         init.parent_names = meson->data->parent_names;
0500         init.num_parents = meson->data->num_parents;
0501 
0502         channel->mux.reg = meson->base + REG_MISC_AB;
0503         channel->mux.shift =
0504                 meson_pwm_per_channel_data[i].clk_sel_shift;
0505         channel->mux.mask = MISC_CLK_SEL_MASK;
0506         channel->mux.flags = 0;
0507         channel->mux.lock = &meson->lock;
0508         channel->mux.table = NULL;
0509         channel->mux.hw.init = &init;
0510 
0511         channel->clk = devm_clk_register(dev, &channel->mux.hw);
0512         if (IS_ERR(channel->clk)) {
0513             err = PTR_ERR(channel->clk);
0514             dev_err(dev, "failed to register %s: %d\n", name, err);
0515             return err;
0516         }
0517 
0518         snprintf(name, sizeof(name), "clkin%u", i);
0519 
0520         channel->clk_parent = devm_clk_get_optional(dev, name);
0521         if (IS_ERR(channel->clk_parent))
0522             return PTR_ERR(channel->clk_parent);
0523     }
0524 
0525     return 0;
0526 }
0527 
0528 static int meson_pwm_probe(struct platform_device *pdev)
0529 {
0530     struct meson_pwm *meson;
0531     int err;
0532 
0533     meson = devm_kzalloc(&pdev->dev, sizeof(*meson), GFP_KERNEL);
0534     if (!meson)
0535         return -ENOMEM;
0536 
0537     meson->base = devm_platform_ioremap_resource(pdev, 0);
0538     if (IS_ERR(meson->base))
0539         return PTR_ERR(meson->base);
0540 
0541     spin_lock_init(&meson->lock);
0542     meson->chip.dev = &pdev->dev;
0543     meson->chip.ops = &meson_pwm_ops;
0544     meson->chip.npwm = MESON_NUM_PWMS;
0545 
0546     meson->data = of_device_get_match_data(&pdev->dev);
0547 
0548     err = meson_pwm_init_channels(meson);
0549     if (err < 0)
0550         return err;
0551 
0552     err = devm_pwmchip_add(&pdev->dev, &meson->chip);
0553     if (err < 0) {
0554         dev_err(&pdev->dev, "failed to register PWM chip: %d\n", err);
0555         return err;
0556     }
0557 
0558     return 0;
0559 }
0560 
0561 static struct platform_driver meson_pwm_driver = {
0562     .driver = {
0563         .name = "meson-pwm",
0564         .of_match_table = meson_pwm_matches,
0565     },
0566     .probe = meson_pwm_probe,
0567 };
0568 module_platform_driver(meson_pwm_driver);
0569 
0570 MODULE_DESCRIPTION("Amlogic Meson PWM Generator driver");
0571 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
0572 MODULE_LICENSE("Dual BSD/GPL");