Commit 9e287e0c authored by Uwe Kleine-König's avatar Uwe Kleine-König

pwm: sti: Maintain all per-chip driver data in a single struct

Instead of (arbitrarily?) spliting the per-chip driver data into two
structures, put everything into struct sti_pwm_chip. This reduces memory
management overhead and a few pointer indirections.

Link: https://lore.kernel.org/r/2788a421ec838ee8f63e76a78b04e1d48b49f959.1710068192.git.u.kleine-koenig@pengutronix.deSigned-off-by: default avatarUwe Kleine-König <u.kleine-koenig@pengutronix.de>
parent 354bf751
...@@ -73,20 +73,16 @@ struct sti_cpt_ddata { ...@@ -73,20 +73,16 @@ struct sti_cpt_ddata {
wait_queue_head_t wait; wait_queue_head_t wait;
}; };
struct sti_pwm_compat_data {
unsigned int pwm_num_devs;
unsigned int cpt_num_devs;
unsigned int max_pwm_cnt;
unsigned int max_prescale;
struct sti_cpt_ddata *ddata;
};
struct sti_pwm_chip { struct sti_pwm_chip {
struct device *dev; struct device *dev;
struct clk *pwm_clk; struct clk *pwm_clk;
struct clk *cpt_clk; struct clk *cpt_clk;
struct regmap *regmap; struct regmap *regmap;
struct sti_pwm_compat_data *cdata; unsigned int pwm_num_devs;
unsigned int cpt_num_devs;
unsigned int max_pwm_cnt;
unsigned int max_prescale;
struct sti_cpt_ddata *ddata;
struct regmap_field *prescale_low; struct regmap_field *prescale_low;
struct regmap_field *prescale_high; struct regmap_field *prescale_high;
struct regmap_field *pwm_out_en; struct regmap_field *pwm_out_en;
...@@ -121,7 +117,6 @@ static inline struct sti_pwm_chip *to_sti_pwmchip(struct pwm_chip *chip) ...@@ -121,7 +117,6 @@ static inline struct sti_pwm_chip *to_sti_pwmchip(struct pwm_chip *chip)
static int sti_pwm_get_prescale(struct sti_pwm_chip *pc, unsigned long period, static int sti_pwm_get_prescale(struct sti_pwm_chip *pc, unsigned long period,
unsigned int *prescale) unsigned int *prescale)
{ {
struct sti_pwm_compat_data *cdata = pc->cdata;
unsigned long clk_rate; unsigned long clk_rate;
unsigned long value; unsigned long value;
unsigned int ps; unsigned int ps;
...@@ -136,13 +131,13 @@ static int sti_pwm_get_prescale(struct sti_pwm_chip *pc, unsigned long period, ...@@ -136,13 +131,13 @@ static int sti_pwm_get_prescale(struct sti_pwm_chip *pc, unsigned long period,
* prescale = ((period_ns * clk_rate) / (10^9 * (max_pwm_cnt + 1)) - 1 * prescale = ((period_ns * clk_rate) / (10^9 * (max_pwm_cnt + 1)) - 1
*/ */
value = NSEC_PER_SEC / clk_rate; value = NSEC_PER_SEC / clk_rate;
value *= cdata->max_pwm_cnt + 1; value *= pc->max_pwm_cnt + 1;
if (period % value) if (period % value)
return -EINVAL; return -EINVAL;
ps = period / value - 1; ps = period / value - 1;
if (ps > cdata->max_prescale) if (ps > pc->max_prescale)
return -EINVAL; return -EINVAL;
*prescale = ps; *prescale = ps;
...@@ -163,7 +158,6 @@ static int sti_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, ...@@ -163,7 +158,6 @@ static int sti_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
int duty_ns, int period_ns) int duty_ns, int period_ns)
{ {
struct sti_pwm_chip *pc = to_sti_pwmchip(chip); struct sti_pwm_chip *pc = to_sti_pwmchip(chip);
struct sti_pwm_compat_data *cdata = pc->cdata;
unsigned int ncfg, value, prescale = 0; unsigned int ncfg, value, prescale = 0;
struct pwm_device *cur = pc->cur; struct pwm_device *cur = pc->cur;
struct device *dev = pc->dev; struct device *dev = pc->dev;
...@@ -223,7 +217,7 @@ static int sti_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, ...@@ -223,7 +217,7 @@ static int sti_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
* PWM pulse = (max_pwm_count + 1) local cycles, * PWM pulse = (max_pwm_count + 1) local cycles,
* that is continuous pulse: signal never goes low. * that is continuous pulse: signal never goes low.
*/ */
value = cdata->max_pwm_cnt * duty_ns / period_ns; value = pc->max_pwm_cnt * duty_ns / period_ns;
ret = regmap_write(pc->regmap, PWM_OUT_VAL(pwm->hwpwm), value); ret = regmap_write(pc->regmap, PWM_OUT_VAL(pwm->hwpwm), value);
if (ret) if (ret)
...@@ -312,14 +306,13 @@ static int sti_pwm_capture(struct pwm_chip *chip, struct pwm_device *pwm, ...@@ -312,14 +306,13 @@ static int sti_pwm_capture(struct pwm_chip *chip, struct pwm_device *pwm,
struct pwm_capture *result, unsigned long timeout) struct pwm_capture *result, unsigned long timeout)
{ {
struct sti_pwm_chip *pc = to_sti_pwmchip(chip); struct sti_pwm_chip *pc = to_sti_pwmchip(chip);
struct sti_pwm_compat_data *cdata = pc->cdata; struct sti_cpt_ddata *ddata = &pc->ddata[pwm->hwpwm];
struct sti_cpt_ddata *ddata = &cdata->ddata[pwm->hwpwm];
struct device *dev = pc->dev; struct device *dev = pc->dev;
unsigned int effective_ticks; unsigned int effective_ticks;
unsigned long long high, low; unsigned long long high, low;
int ret; int ret;
if (pwm->hwpwm >= cdata->cpt_num_devs) { if (pwm->hwpwm >= pc->cpt_num_devs) {
dev_err(dev, "device %u is not valid\n", pwm->hwpwm); dev_err(dev, "device %u is not valid\n", pwm->hwpwm);
return -EINVAL; return -EINVAL;
} }
...@@ -394,11 +387,10 @@ static int sti_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, ...@@ -394,11 +387,10 @@ static int sti_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
const struct pwm_state *state) const struct pwm_state *state)
{ {
struct sti_pwm_chip *pc = to_sti_pwmchip(chip); struct sti_pwm_chip *pc = to_sti_pwmchip(chip);
struct sti_pwm_compat_data *cdata = pc->cdata;
struct device *dev = pc->dev; struct device *dev = pc->dev;
int err; int err;
if (pwm->hwpwm >= cdata->pwm_num_devs) { if (pwm->hwpwm >= pc->pwm_num_devs) {
dev_err(dev, "device %u is not valid for pwm mode\n", dev_err(dev, "device %u is not valid for pwm mode\n",
pwm->hwpwm); pwm->hwpwm);
return -EINVAL; return -EINVAL;
...@@ -447,7 +439,7 @@ static irqreturn_t sti_pwm_interrupt(int irq, void *data) ...@@ -447,7 +439,7 @@ static irqreturn_t sti_pwm_interrupt(int irq, void *data)
while (cpt_int_stat) { while (cpt_int_stat) {
devicenum = ffs(cpt_int_stat) - 1; devicenum = ffs(cpt_int_stat) - 1;
ddata = &pc->cdata->ddata[devicenum]; ddata = &pc->ddata[devicenum];
/* /*
* Capture input: * Capture input:
...@@ -551,7 +543,6 @@ static int sti_pwm_probe(struct platform_device *pdev) ...@@ -551,7 +543,6 @@ static int sti_pwm_probe(struct platform_device *pdev)
u32 num_devs; u32 num_devs;
unsigned int pwm_num_devs = 0; unsigned int pwm_num_devs = 0;
unsigned int cpt_num_devs = 0; unsigned int cpt_num_devs = 0;
struct sti_pwm_compat_data *cdata;
struct pwm_chip *chip; struct pwm_chip *chip;
struct sti_pwm_chip *pc; struct sti_pwm_chip *pc;
unsigned int i; unsigned int i;
...@@ -573,10 +564,6 @@ static int sti_pwm_probe(struct platform_device *pdev) ...@@ -573,10 +564,6 @@ static int sti_pwm_probe(struct platform_device *pdev)
return PTR_ERR(chip); return PTR_ERR(chip);
pc = to_sti_pwmchip(chip); pc = to_sti_pwmchip(chip);
cdata = devm_kzalloc(dev, sizeof(*cdata), GFP_KERNEL);
if (!cdata)
return -ENOMEM;
pc->mmio = devm_platform_ioremap_resource(pdev, 0); pc->mmio = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(pc->mmio)) if (IS_ERR(pc->mmio))
return PTR_ERR(pc->mmio); return PTR_ERR(pc->mmio);
...@@ -600,12 +587,11 @@ static int sti_pwm_probe(struct platform_device *pdev) ...@@ -600,12 +587,11 @@ static int sti_pwm_probe(struct platform_device *pdev)
* Setup PWM data with default values: some values could be replaced * Setup PWM data with default values: some values could be replaced
* with specific ones provided from Device Tree. * with specific ones provided from Device Tree.
*/ */
cdata->max_prescale = 0xff; pc->max_prescale = 0xff;
cdata->max_pwm_cnt = 255; pc->max_pwm_cnt = 255;
cdata->pwm_num_devs = pwm_num_devs; pc->pwm_num_devs = pwm_num_devs;
cdata->cpt_num_devs = cpt_num_devs; pc->cpt_num_devs = cpt_num_devs;
pc->cdata = cdata;
pc->dev = dev; pc->dev = dev;
pc->en_count = 0; pc->en_count = 0;
mutex_init(&pc->sti_pwm_lock); mutex_init(&pc->sti_pwm_lock);
...@@ -614,28 +600,28 @@ static int sti_pwm_probe(struct platform_device *pdev) ...@@ -614,28 +600,28 @@ static int sti_pwm_probe(struct platform_device *pdev)
if (ret) if (ret)
return dev_err_probe(dev, ret, "Failed to initialize regmap fields\n"); return dev_err_probe(dev, ret, "Failed to initialize regmap fields\n");
if (cdata->pwm_num_devs) { if (pc->pwm_num_devs) {
pc->pwm_clk = devm_clk_get_prepared(dev, "pwm"); pc->pwm_clk = devm_clk_get_prepared(dev, "pwm");
if (IS_ERR(pc->pwm_clk)) if (IS_ERR(pc->pwm_clk))
return dev_err_probe(dev, PTR_ERR(pc->pwm_clk), return dev_err_probe(dev, PTR_ERR(pc->pwm_clk),
"failed to get PWM clock\n"); "failed to get PWM clock\n");
} }
if (cdata->cpt_num_devs) { if (pc->cpt_num_devs) {
pc->cpt_clk = devm_clk_get_prepared(dev, "capture"); pc->cpt_clk = devm_clk_get_prepared(dev, "capture");
if (IS_ERR(pc->cpt_clk)) if (IS_ERR(pc->cpt_clk))
return dev_err_probe(dev, PTR_ERR(pc->cpt_clk), return dev_err_probe(dev, PTR_ERR(pc->cpt_clk),
"failed to get PWM capture clock\n"); "failed to get PWM capture clock\n");
cdata->ddata = devm_kzalloc(dev, cdata->cpt_num_devs * sizeof(*cdata->ddata), GFP_KERNEL); pc->ddata = devm_kzalloc(dev, pc->cpt_num_devs * sizeof(*pc->ddata), GFP_KERNEL);
if (!cdata->ddata) if (!pc->ddata)
return -ENOMEM; return -ENOMEM;
} }
chip->ops = &sti_pwm_ops; chip->ops = &sti_pwm_ops;
for (i = 0; i < cdata->cpt_num_devs; i++) { for (i = 0; i < pc->cpt_num_devs; i++) {
struct sti_cpt_ddata *ddata = &cdata->ddata[i]; struct sti_cpt_ddata *ddata = &pc->ddata[i];
init_waitqueue_head(&ddata->wait); init_waitqueue_head(&ddata->wait);
mutex_init(&ddata->lock); mutex_init(&ddata->lock);
......
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