Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/drivers/pinctrl/sophgo/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 7 kB image not shown  

Quelle  pinctrl-sg2042-ops.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * Sophgo sg2042 SoCs pinctrl driver.
 *
 * Copyright (C) 2024 Inochi Amaoto <inochiama@outlook.com>
 *
 */


#include <linux/bitfield.h>
#include <linux/bits.h>
#include <linux/cleanup.h>
#include <linux/export.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/seq_file.h>
#include <linux/spinlock.h>

#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>

#include "../pinctrl-utils.h"
#include "../pinmux.h"

#include "pinctrl-sg2042.h"

#define PIN_IO_PULL_ONE_ENABLE  BIT(0)
#define PIN_IO_PULL_DIR_UP  (BIT(1) | PIN_IO_PULL_ONE_ENABLE)
#define PIN_IO_PULL_DIR_DOWN  (0 | PIN_IO_PULL_ONE_ENABLE)
#define PIN_IO_PULL_ONE_MASK  GENMASK(1, 0)

#define PIN_IO_PULL_UP   BIT(2)
#define PIN_IO_PULL_UP_DONW  BIT(3)
#define PIN_IO_PULL_UP_MASK  GENMASK(3, 2)

#define PIN_IO_MUX   GENMASK(5, 4)
#define PIN_IO_DRIVE   GENMASK(9, 6)
#define PIN_IO_SCHMITT_ENABLE  BIT(10)
#define PIN_IO_OUTPUT_ENABLE  BIT(11)

struct sg2042_priv {
 void __iomem    *regs;
};

static u8 sg2042_dt_get_pin_mux(u32 value)
{
 return value >> 16;
}

static inline u32 sg2042_get_pin_reg(struct sophgo_pinctrl *pctrl,
         const struct sophgo_pin *sp)
{
 struct sg2042_priv *priv = pctrl->priv_ctrl;
 const struct sg2042_pin *pin = sophgo_to_sg2042_pin(sp);
 void __iomem *reg = priv->regs + pin->offset;

 if (sp->flags & PIN_FLAG_WRITE_HIGH)
  return readl(reg) >> 16;
 else
  return readl(reg) & 0xffff;
}

static int sg2042_set_pin_reg(struct sophgo_pinctrl *pctrl,
         const struct sophgo_pin *sp,
         u32 value, u32 mask)
{
 struct sg2042_priv *priv = pctrl->priv_ctrl;
 const struct sg2042_pin *pin = sophgo_to_sg2042_pin(sp);
 void __iomem *reg = priv->regs + pin->offset;
 u32 v = readl(reg);

 if (sp->flags & PIN_FLAG_WRITE_HIGH) {
  v &= ~(mask << 16);
  v |= value << 16;
 } else {
  v &= ~mask;
  v |= value;
 }

 writel(v, reg);

 return 0;
}

static void sg2042_pctrl_dbg_show(struct pinctrl_dev *pctldev,
      struct seq_file *seq, unsigned int pin_id)
{
 struct sophgo_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
 const struct sophgo_pin *sp = sophgo_get_pin(pctrl, pin_id);
 u32 value, mux;

 value = sg2042_get_pin_reg(pctrl, sp);
 mux = FIELD_GET(PIN_IO_MUX, value);
 seq_printf(seq, "mux:%u reg:0x%04x ", mux, value);
}

const struct pinctrl_ops sg2042_pctrl_ops = {
 .get_groups_count = pinctrl_generic_get_group_count,
 .get_group_name  = pinctrl_generic_get_group_name,
 .get_group_pins  = pinctrl_generic_get_group_pins,
 .pin_dbg_show  = sg2042_pctrl_dbg_show,
 .dt_node_to_map  = sophgo_pctrl_dt_node_to_map,
 .dt_free_map  = pinctrl_utils_free_map,
};
EXPORT_SYMBOL_GPL(sg2042_pctrl_ops);

static void sg2042_set_pinmux_config(struct sophgo_pinctrl *pctrl,
         const struct sophgo_pin *sp, u32 config)
{
 u32 mux = sg2042_dt_get_pin_mux(config);

 if (!(sp->flags & PIN_FLAG_NO_PINMUX))
  sg2042_set_pin_reg(pctrl, sp, mux, PIN_IO_MUX);
}

const struct pinmux_ops sg2042_pmx_ops = {
 .get_functions_count = pinmux_generic_get_function_count,
 .get_function_name = pinmux_generic_get_function_name,
 .get_function_groups = pinmux_generic_get_function_groups,
 .set_mux  = sophgo_pmx_set_mux,
 .strict   = true,
};
EXPORT_SYMBOL_GPL(sg2042_pmx_ops);

static int sg2042_pconf_get(struct pinctrl_dev *pctldev,
       unsigned int pin_id, unsigned long *config)
{
 struct sophgo_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
 int param = pinconf_to_config_param(*config);
 const struct sophgo_pin *sp = sophgo_get_pin(pctrl, pin_id);
 u32 value;
 u32 arg;
 bool enabled;
 int ret;

 if (!sp)
  return -EINVAL;

 value = sg2042_get_pin_reg(pctrl, sp);

 switch (param) {
 case PIN_CONFIG_BIAS_DISABLE:
  if (sp->flags & PIN_FLAG_ONLY_ONE_PULL)
   arg = FIELD_GET(PIN_IO_PULL_ONE_ENABLE, value);
  else
   arg = FIELD_GET(PIN_IO_PULL_UP_MASK, value);
  enabled = arg == 0;
  break;
 case PIN_CONFIG_BIAS_PULL_DOWN:
  if (sp->flags & PIN_FLAG_ONLY_ONE_PULL) {
   arg = FIELD_GET(PIN_IO_PULL_ONE_MASK, value);
   enabled = arg == PIN_IO_PULL_DIR_DOWN;
  } else {
   enabled = FIELD_GET(PIN_IO_PULL_UP_DONW, value) != 0;
  }
  arg = sophgo_pinctrl_typical_pull_down(pctrl, sp, NULL);
  break;
 case PIN_CONFIG_BIAS_PULL_UP:
  if (sp->flags & PIN_FLAG_ONLY_ONE_PULL) {
   arg = FIELD_GET(PIN_IO_PULL_ONE_MASK, value);
   enabled = arg == PIN_IO_PULL_DIR_UP;
  } else {
   enabled = FIELD_GET(PIN_IO_PULL_UP, value) != 0;
  }
  arg = sophgo_pinctrl_typical_pull_up(pctrl, sp, NULL);
  break;
 case PIN_CONFIG_DRIVE_STRENGTH_UA:
  enabled = FIELD_GET(PIN_IO_OUTPUT_ENABLE, value) != 0;
  arg = FIELD_GET(PIN_IO_DRIVE, value);
  ret = sophgo_pinctrl_reg2oc(pctrl, sp, NULL, arg);
  if (ret < 0)
   return ret;
  arg = ret;
  break;
 case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
  arg = FIELD_GET(PIN_IO_SCHMITT_ENABLE, value);
  enabled = arg != 0;
  break;
 default:
  return -ENOTSUPP;
 }

 *config = pinconf_to_config_packed(param, arg);

 return enabled ? 0 : -EINVAL;
}

static int sg2042_pinconf_compute_config(struct sophgo_pinctrl *pctrl,
      const struct sophgo_pin *sp,
      unsigned long *configs,
      unsigned int num_configs,
      u32 *value, u32 *mask)
{
 int i;
 u16 v = 0, m = 0;
 int ret;

 if (!sp)
  return -EINVAL;

 for (i = 0; i < num_configs; i++) {
  int param = pinconf_to_config_param(configs[i]);
  u32 arg = pinconf_to_config_argument(configs[i]);

  switch (param) {
  case PIN_CONFIG_BIAS_DISABLE:
   if (sp->flags & PIN_FLAG_ONLY_ONE_PULL) {
    v &= ~PIN_IO_PULL_ONE_ENABLE;
    m |= PIN_IO_PULL_ONE_ENABLE;
   } else {
    v &= ~PIN_IO_PULL_UP_MASK;
    m |= PIN_IO_PULL_UP_MASK;
   }
   break;
  case PIN_CONFIG_BIAS_PULL_DOWN:
   if (sp->flags & PIN_FLAG_ONLY_ONE_PULL) {
    v &= ~PIN_IO_PULL_ONE_MASK;
    v |= PIN_IO_PULL_DIR_DOWN;
    m |= PIN_IO_PULL_ONE_MASK;
   } else {
    v |= PIN_IO_PULL_UP_DONW;
    m |= PIN_IO_PULL_UP_DONW;
   }
   break;
  case PIN_CONFIG_BIAS_PULL_UP:
   if (sp->flags & PIN_FLAG_ONLY_ONE_PULL) {
    v &= ~PIN_IO_PULL_ONE_MASK;
    v |= PIN_IO_PULL_DIR_UP;
    m |= PIN_IO_PULL_ONE_MASK;
   } else {
    v |= PIN_IO_PULL_UP;
    m |= PIN_IO_PULL_UP;
   }
   break;
  case PIN_CONFIG_DRIVE_STRENGTH_UA:
   v &= ~(PIN_IO_DRIVE | PIN_IO_OUTPUT_ENABLE);
   if (arg != 0) {
    ret = sophgo_pinctrl_oc2reg(pctrl, sp, NULL, arg);
    if (ret < 0)
     return ret;
    if (!(sp->flags & PIN_FLAG_NO_OEX_EN))
     v |= PIN_IO_OUTPUT_ENABLE;
    v |= FIELD_PREP(PIN_IO_DRIVE, ret);
   }
   m |= PIN_IO_DRIVE | PIN_IO_OUTPUT_ENABLE;
   break;
  case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
   v |= PIN_IO_SCHMITT_ENABLE;
   m |= PIN_IO_SCHMITT_ENABLE;
   break;
  default:
   return -ENOTSUPP;
  }
 }

 *value = v;
 *mask = m;

 return 0;
}

const struct pinconf_ops sg2042_pconf_ops = {
 .pin_config_get   = sg2042_pconf_get,
 .pin_config_set   = sophgo_pconf_set,
 .pin_config_group_set  = sophgo_pconf_group_set,
 .is_generic   = true,
};
EXPORT_SYMBOL_GPL(sg2042_pconf_ops);

static int sophgo_pinctrl_init(struct platform_device *pdev,
          struct sophgo_pinctrl *pctrl)
{
 struct sg2042_priv *priv;

 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
 if (!priv)
  return -ENOMEM;

 priv->regs = devm_platform_ioremap_resource(pdev, 0);
 if (IS_ERR(priv->regs))
  return PTR_ERR(priv->regs);

 pctrl->priv_ctrl = priv;

 return 0;
}

const struct sophgo_cfg_ops sg2042_cfg_ops = {
 .pctrl_init = sophgo_pinctrl_init,
 .compute_pinconf_config = sg2042_pinconf_compute_config,
 .set_pinconf_config = sg2042_set_pin_reg,
 .set_pinmux_config = sg2042_set_pinmux_config,
};
EXPORT_SYMBOL_GPL(sg2042_cfg_ops);

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

¤ Dauer der Verarbeitung: 0.3 Sekunden  ¤

*© 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.