Commit 5ec8c48a authored by Thierry Reding's avatar Thierry Reding

Merge branch 'for-4.13/drivers' into for-next

parents 72f2ebbd e47866a1
...@@ -118,10 +118,8 @@ static int bfin_pwm_probe(struct platform_device *pdev) ...@@ -118,10 +118,8 @@ static int bfin_pwm_probe(struct platform_device *pdev)
int ret; int ret;
pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL);
if (!pwm) { if (!pwm)
dev_err(&pdev->dev, "failed to allocate memory\n");
return -ENOMEM; return -ENOMEM;
}
platform_set_drvdata(pdev, pwm); platform_set_drvdata(pdev, pwm);
......
...@@ -75,8 +75,8 @@ static int __cros_ec_pwm_get_duty(struct cros_ec_device *ec, u8 index, ...@@ -75,8 +75,8 @@ static int __cros_ec_pwm_get_duty(struct cros_ec_device *ec, u8 index,
msg->version = 0; msg->version = 0;
msg->command = EC_CMD_PWM_GET_DUTY; msg->command = EC_CMD_PWM_GET_DUTY;
msg->insize = sizeof(*params); msg->insize = sizeof(*resp);
msg->outsize = sizeof(*resp); msg->outsize = sizeof(*params);
params->pwm_type = EC_PWM_TYPE_GENERIC; params->pwm_type = EC_PWM_TYPE_GENERIC;
params->index = index; params->index = index;
......
...@@ -165,7 +165,7 @@ static int hibvt_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, ...@@ -165,7 +165,7 @@ static int hibvt_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
return 0; return 0;
} }
static struct pwm_ops hibvt_pwm_ops = { static const struct pwm_ops hibvt_pwm_ops = {
.get_state = hibvt_pwm_get_state, .get_state = hibvt_pwm_get_state,
.apply = hibvt_pwm_apply, .apply = hibvt_pwm_apply,
......
...@@ -103,6 +103,7 @@ struct meson_pwm_channel { ...@@ -103,6 +103,7 @@ struct meson_pwm_channel {
struct meson_pwm_data { struct meson_pwm_data {
const char * const *parent_names; const char * const *parent_names;
unsigned int num_parents;
}; };
struct meson_pwm { struct meson_pwm {
...@@ -162,7 +163,8 @@ static int meson_pwm_calc(struct meson_pwm *meson, ...@@ -162,7 +163,8 @@ static int meson_pwm_calc(struct meson_pwm *meson,
unsigned int duty, unsigned int period) unsigned int duty, unsigned int period)
{ {
unsigned int pre_div, cnt, duty_cnt; unsigned int pre_div, cnt, duty_cnt;
unsigned long fin_freq = -1, fin_ns; unsigned long fin_freq = -1;
u64 fin_ps;
if (~(meson->inverter_mask >> id) & 0x1) if (~(meson->inverter_mask >> id) & 0x1)
duty = period - duty; duty = period - duty;
...@@ -178,13 +180,15 @@ static int meson_pwm_calc(struct meson_pwm *meson, ...@@ -178,13 +180,15 @@ static int meson_pwm_calc(struct meson_pwm *meson,
} }
dev_dbg(meson->chip.dev, "fin_freq: %lu Hz\n", fin_freq); dev_dbg(meson->chip.dev, "fin_freq: %lu Hz\n", fin_freq);
fin_ns = NSEC_PER_SEC / fin_freq; fin_ps = (u64)NSEC_PER_SEC * 1000;
do_div(fin_ps, fin_freq);
/* Calc pre_div with the period */ /* Calc pre_div with the period */
for (pre_div = 0; pre_div < MISC_CLK_DIV_MASK; pre_div++) { for (pre_div = 0; pre_div < MISC_CLK_DIV_MASK; pre_div++) {
cnt = DIV_ROUND_CLOSEST(period, fin_ns * (pre_div + 1)); cnt = DIV_ROUND_CLOSEST_ULL((u64)period * 1000,
dev_dbg(meson->chip.dev, "fin_ns=%lu pre_div=%u cnt=%u\n", fin_ps * (pre_div + 1));
fin_ns, pre_div, cnt); dev_dbg(meson->chip.dev, "fin_ps=%llu pre_div=%u cnt=%u\n",
fin_ps, pre_div, cnt);
if (cnt <= 0xffff) if (cnt <= 0xffff)
break; break;
} }
...@@ -207,7 +211,8 @@ static int meson_pwm_calc(struct meson_pwm *meson, ...@@ -207,7 +211,8 @@ static int meson_pwm_calc(struct meson_pwm *meson,
channel->lo = cnt; channel->lo = cnt;
} else { } else {
/* Then check is we can have the duty with the same pre_div */ /* Then check is we can have the duty with the same pre_div */
duty_cnt = DIV_ROUND_CLOSEST(duty, fin_ns * (pre_div + 1)); duty_cnt = DIV_ROUND_CLOSEST_ULL((u64)duty * 1000,
fin_ps * (pre_div + 1));
if (duty_cnt > 0xffff) { if (duty_cnt > 0xffff) {
dev_err(meson->chip.dev, "unable to get duty cycle\n"); dev_err(meson->chip.dev, "unable to get duty cycle\n");
return -EINVAL; return -EINVAL;
...@@ -381,6 +386,7 @@ static const char * const pwm_meson8b_parent_names[] = { ...@@ -381,6 +386,7 @@ static const char * const pwm_meson8b_parent_names[] = {
static const struct meson_pwm_data pwm_meson8b_data = { static const struct meson_pwm_data pwm_meson8b_data = {
.parent_names = pwm_meson8b_parent_names, .parent_names = pwm_meson8b_parent_names,
.num_parents = ARRAY_SIZE(pwm_meson8b_parent_names),
}; };
static const char * const pwm_gxbb_parent_names[] = { static const char * const pwm_gxbb_parent_names[] = {
...@@ -389,11 +395,35 @@ static const char * const pwm_gxbb_parent_names[] = { ...@@ -389,11 +395,35 @@ static const char * const pwm_gxbb_parent_names[] = {
static const struct meson_pwm_data pwm_gxbb_data = { static const struct meson_pwm_data pwm_gxbb_data = {
.parent_names = pwm_gxbb_parent_names, .parent_names = pwm_gxbb_parent_names,
.num_parents = ARRAY_SIZE(pwm_gxbb_parent_names),
};
/*
* Only the 2 first inputs of the GXBB AO PWMs are valid
* The last 2 are grounded
*/
static const char * const pwm_gxbb_ao_parent_names[] = {
"xtal", "clk81"
};
static const struct meson_pwm_data pwm_gxbb_ao_data = {
.parent_names = pwm_gxbb_ao_parent_names,
.num_parents = ARRAY_SIZE(pwm_gxbb_ao_parent_names),
}; };
static const struct of_device_id meson_pwm_matches[] = { static const struct of_device_id meson_pwm_matches[] = {
{ .compatible = "amlogic,meson8b-pwm", .data = &pwm_meson8b_data }, {
{ .compatible = "amlogic,meson-gxbb-pwm", .data = &pwm_gxbb_data }, .compatible = "amlogic,meson8b-pwm",
.data = &pwm_meson8b_data
},
{
.compatible = "amlogic,meson-gxbb-pwm",
.data = &pwm_gxbb_data
},
{
.compatible = "amlogic,meson-gxbb-ao-pwm",
.data = &pwm_gxbb_ao_data
},
{}, {},
}; };
MODULE_DEVICE_TABLE(of, meson_pwm_matches); MODULE_DEVICE_TABLE(of, meson_pwm_matches);
...@@ -417,7 +447,7 @@ static int meson_pwm_init_channels(struct meson_pwm *meson, ...@@ -417,7 +447,7 @@ static int meson_pwm_init_channels(struct meson_pwm *meson,
init.ops = &clk_mux_ops; init.ops = &clk_mux_ops;
init.flags = CLK_IS_BASIC; init.flags = CLK_IS_BASIC;
init.parent_names = meson->data->parent_names; init.parent_names = meson->data->parent_names;
init.num_parents = 1 << MISC_CLK_SEL_WIDTH; init.num_parents = meson->data->num_parents;
channel->mux.reg = meson->base + REG_MISC_AB; channel->mux.reg = meson->base + REG_MISC_AB;
channel->mux.shift = mux_reg_shifts[i]; channel->mux.shift = mux_reg_shifts[i];
......
This diff is collapsed.
...@@ -41,6 +41,9 @@ ...@@ -41,6 +41,9 @@
struct tegra_pwm_soc { struct tegra_pwm_soc {
unsigned int num_channels; unsigned int num_channels;
/* Maximum IP frequency for given SoCs */
unsigned long max_frequency;
}; };
struct tegra_pwm_chip { struct tegra_pwm_chip {
...@@ -201,7 +204,18 @@ static int tegra_pwm_probe(struct platform_device *pdev) ...@@ -201,7 +204,18 @@ static int tegra_pwm_probe(struct platform_device *pdev)
if (IS_ERR(pwm->clk)) if (IS_ERR(pwm->clk))
return PTR_ERR(pwm->clk); return PTR_ERR(pwm->clk);
/* Read PWM clock rate from source */ /* Set maximum frequency of the IP */
ret = clk_set_rate(pwm->clk, pwm->soc->max_frequency);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to set max frequency: %d\n", ret);
return ret;
}
/*
* The requested and configured frequency may differ due to
* clock register resolutions. Get the configured frequency
* so that PWM period can be calculated more accurately.
*/
pwm->clk_rate = clk_get_rate(pwm->clk); pwm->clk_rate = clk_get_rate(pwm->clk);
pwm->rst = devm_reset_control_get(&pdev->dev, "pwm"); pwm->rst = devm_reset_control_get(&pdev->dev, "pwm");
...@@ -273,10 +287,12 @@ static int tegra_pwm_resume(struct device *dev) ...@@ -273,10 +287,12 @@ static int tegra_pwm_resume(struct device *dev)
static const struct tegra_pwm_soc tegra20_pwm_soc = { static const struct tegra_pwm_soc tegra20_pwm_soc = {
.num_channels = 4, .num_channels = 4,
.max_frequency = 48000000UL,
}; };
static const struct tegra_pwm_soc tegra186_pwm_soc = { static const struct tegra_pwm_soc tegra186_pwm_soc = {
.num_channels = 1, .num_channels = 1,
.max_frequency = 102000000UL,
}; };
static const struct of_device_id tegra_pwm_of_match[] = { static const struct of_device_id tegra_pwm_of_match[] = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment