Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  pwm-crc.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2015 Intel Corporation. All rights reserved.
 *
 * Author: Shobhit Kumar <shobhit.kumar@intel.com>
 */


#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/mfd/intel_soc_pmic.h>
#include <linux/pwm.h>

#define PWM0_CLK_DIV  0x4B
#define  PWM_OUTPUT_ENABLE BIT(7)
#define  PWM_DIV_CLK_0  0x00 /* DIVIDECLK = BASECLK */
#define  PWM_DIV_CLK_100 0x63 /* DIVIDECLK = BASECLK/100 */
#define  PWM_DIV_CLK_128 0x7F /* DIVIDECLK = BASECLK/128 */

#define PWM0_DUTY_CYCLE  0x4E
#define BACKLIGHT_EN  0x51

#define PWM_MAX_LEVEL  0xFF

#define PWM_BASE_CLK_MHZ 6 /* 6 MHz */
#define PWM_MAX_PERIOD_NS 5461334 /* 183 Hz */

/**
 * struct crystalcove_pwm - Crystal Cove PWM controller
 * @regmap: the regmap from the parent device.
 */

struct crystalcove_pwm {
 struct regmap *regmap;
};

static inline struct crystalcove_pwm *to_crc_pwm(struct pwm_chip *chip)
{
 return pwmchip_get_drvdata(chip);
}

static int crc_pwm_calc_clk_div(int period_ns)
{
 int clk_div;

 clk_div = PWM_BASE_CLK_MHZ * period_ns / (256 * NSEC_PER_USEC);
 /* clk_div 1 - 128, maps to register values 0-127 */
 if (clk_div > 0)
  clk_div--;

 return clk_div;
}

static int crc_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
    const struct pwm_state *state)
{
 struct crystalcove_pwm *crc_pwm = to_crc_pwm(chip);
 struct device *dev = pwmchip_parent(chip);
 int err;

 if (state->period > PWM_MAX_PERIOD_NS) {
  dev_err(dev, "un-supported period_ns\n");
  return -EINVAL;
 }

 if (state->polarity != PWM_POLARITY_NORMAL)
  return -EINVAL;

 if (pwm_is_enabled(pwm) && !state->enabled) {
  err = regmap_write(crc_pwm->regmap, BACKLIGHT_EN, 0);
  if (err) {
   dev_err(dev, "Error writing BACKLIGHT_EN %d\n", err);
   return err;
  }
 }

 if (pwm_get_duty_cycle(pwm) != state->duty_cycle ||
     pwm_get_period(pwm) != state->period) {
  u64 level = state->duty_cycle * PWM_MAX_LEVEL;

  do_div(level, state->period);

  err = regmap_write(crc_pwm->regmap, PWM0_DUTY_CYCLE, level);
  if (err) {
   dev_err(dev, "Error writing PWM0_DUTY_CYCLE %d\n", err);
   return err;
  }
 }

 if (pwm_is_enabled(pwm) && state->enabled &&
     pwm_get_period(pwm) != state->period) {
  /* changing the clk divisor, clear PWM_OUTPUT_ENABLE first */
  err = regmap_write(crc_pwm->regmap, PWM0_CLK_DIV, 0);
  if (err) {
   dev_err(dev, "Error writing PWM0_CLK_DIV %d\n", err);
   return err;
  }
 }

 if (pwm_get_period(pwm) != state->period ||
     pwm_is_enabled(pwm) != state->enabled) {
  int clk_div = crc_pwm_calc_clk_div(state->period);
  int pwm_output_enable = state->enabled ? PWM_OUTPUT_ENABLE : 0;

  err = regmap_write(crc_pwm->regmap, PWM0_CLK_DIV,
       clk_div | pwm_output_enable);
  if (err) {
   dev_err(dev, "Error writing PWM0_CLK_DIV %d\n", err);
   return err;
  }
 }

 if (!pwm_is_enabled(pwm) && state->enabled) {
  err = regmap_write(crc_pwm->regmap, BACKLIGHT_EN, 1);
  if (err) {
   dev_err(dev, "Error writing BACKLIGHT_EN %d\n", err);
   return err;
  }
 }

 return 0;
}

static int crc_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
        struct pwm_state *state)
{
 struct crystalcove_pwm *crc_pwm = to_crc_pwm(chip);
 struct device *dev = pwmchip_parent(chip);
 unsigned int clk_div, clk_div_reg, duty_cycle_reg;
 int error;

 error = regmap_read(crc_pwm->regmap, PWM0_CLK_DIV, &clk_div_reg);
 if (error) {
  dev_err(dev, "Error reading PWM0_CLK_DIV %d\n", error);
  return error;
 }

 error = regmap_read(crc_pwm->regmap, PWM0_DUTY_CYCLE, &duty_cycle_reg);
 if (error) {
  dev_err(dev, "Error reading PWM0_DUTY_CYCLE %d\n", error);
  return error;
 }

 clk_div = (clk_div_reg & ~PWM_OUTPUT_ENABLE) + 1;

 state->period =
  DIV_ROUND_UP(clk_div * NSEC_PER_USEC * 256, PWM_BASE_CLK_MHZ);
 state->duty_cycle =
  DIV_ROUND_UP_ULL(duty_cycle_reg * state->period, PWM_MAX_LEVEL);
 state->polarity = PWM_POLARITY_NORMAL;
 state->enabled = !!(clk_div_reg & PWM_OUTPUT_ENABLE);

 return 0;
}

static const struct pwm_ops crc_pwm_ops = {
 .apply = crc_pwm_apply,
 .get_state = crc_pwm_get_state,
};

static int crystalcove_pwm_probe(struct platform_device *pdev)
{
 struct pwm_chip *chip;
 struct crystalcove_pwm *crc_pwm;
 struct device *dev = pdev->dev.parent;
 struct intel_soc_pmic *pmic = dev_get_drvdata(dev);

 chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*crc_pwm));
 if (IS_ERR(chip))
  return PTR_ERR(chip);
 crc_pwm = to_crc_pwm(chip);

 chip->ops = &crc_pwm_ops;

 /* get the PMIC regmap */
 crc_pwm->regmap = pmic->regmap;

 return devm_pwmchip_add(&pdev->dev, chip);
}

static struct platform_driver crystalcove_pwm_driver = {
 .probe = crystalcove_pwm_probe,
 .driver = {
  .name = "crystal_cove_pwm",
 },
};
module_platform_driver(crystalcove_pwm_driver);

MODULE_ALIAS("platform:crystal_cove_pwm");
MODULE_DESCRIPTION("Intel Crystalcove (CRC) PWM support");
MODULE_LICENSE("GPL");

Messung V0.5
C=94 H=93 G=93

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge