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

Quelle  pinctrl-k1.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2024 Yixun Lan <dlan@gentoo.org> */

#include <linux/bits.h>
#include <linux/clk.h>
#include <linux/cleanup.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/module.h>
#include <linux/mutex.h>

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

#include "../core.h"
#include "../pinctrl-utils.h"
#include "../pinconf.h"
#include "../pinmux.h"
#include "pinctrl-k1.h"

/*
 * +---------+----------+-----------+--------+--------+----------+--------+
 * |   pull  |   drive  | schmitter |  slew  |  edge  |  strong  |   mux  |
 * | up/down | strength |  trigger  |  rate  | detect |   pull   |  mode  |
 * +---------+----------+-----------+--------+--------+----------+--------+
 *   3 bits     3 bits     2 bits     1 bit    3 bits     1 bit    3 bits
 */


#define PAD_MUX   GENMASK(2, 0)
#define PAD_STRONG_PULL  BIT(3)
#define PAD_EDGE_RISE  BIT(4)
#define PAD_EDGE_FALL  BIT(5)
#define PAD_EDGE_CLEAR  BIT(6)
#define PAD_SLEW_RATE  GENMASK(12, 11)
#define PAD_SLEW_RATE_EN BIT(7)
#define PAD_SCHMITT  GENMASK(9, 8)
#define PAD_DRIVE  GENMASK(12, 10)
#define PAD_PULLDOWN  BIT(13)
#define PAD_PULLUP  BIT(14)
#define PAD_PULL_EN  BIT(15)

struct spacemit_pin {
 u16    pin;
 u16    flags;
 u8    gpiofunc;
};

struct spacemit_pinctrl {
 struct device    *dev;
 struct pinctrl_dev   *pctl_dev;
 const struct spacemit_pinctrl_data *data;
 struct pinctrl_desc   pdesc;

 struct mutex    mutex;
 raw_spinlock_t    lock;

 void __iomem    *regs;
};

struct spacemit_pinctrl_data {
 const struct pinctrl_pin_desc   *pins;
 const struct spacemit_pin *data;
 u16    npins;
};

struct spacemit_pin_mux_config {
 const struct spacemit_pin *pin;
 u32    config;
};

struct spacemit_pin_drv_strength {
 u8  val;
 u32  mA;
};

/* map pin id to pinctrl register offset, refer MFPR definition */
static unsigned int spacemit_pin_to_offset(unsigned int pin)
{
 unsigned int offset = 0;

 switch (pin) {
 case 0 ... 85:
  offset = pin + 1;
  break;
 case 86 ... 92:
  offset = pin + 37;
  break;
 case 93 ... 97:
  offset = pin + 24;
  break;
 case 98:
  offset = 93;
  break;
 case 99:
  offset = 92;
  break;
 case 100:
  offset = 91;
  break;
 case 101:
  offset = 90;
  break;
 case 102:
  offset = 95;
  break;
 case 103:
  offset = 94;
  break;
 case 104 ... 110:
  offset = pin + 6;
  break;
 case 111 ... 127:
  offset = pin + 20;
  break;
 default:
  break;
 }

 return offset << 2;
}

static inline void __iomem *spacemit_pin_to_reg(struct spacemit_pinctrl *pctrl,
      unsigned int pin)
{
 return pctrl->regs + spacemit_pin_to_offset(pin);
}

static u16 spacemit_dt_get_pin(u32 value)
{
 return value >> 16;
}

static u16 spacemit_dt_get_pin_mux(u32 value)
{
 return value & GENMASK(15, 0);
}

static const struct spacemit_pin *spacemit_get_pin(struct spacemit_pinctrl *pctrl,
         unsigned long pin)
{
 const struct spacemit_pin *pdata = pctrl->data->data;
 int i;

 for (i = 0; i < pctrl->data->npins; i++) {
  if (pin == pdata[i].pin)
   return &pdata[i];
 }

 return NULL;
}

static inline enum spacemit_pin_io_type spacemit_to_pin_io_type(
 const struct spacemit_pin *pin)
{
 return K1_PIN_GET_IO_TYPE(pin->flags);
}

/* External: IO voltage via external source, can be 1.8V or 3.3V */
static const char * const io_type_desc[] = {
 "None",
 "Fixed/1V8",
 "Fixed/3V3",
 "External",
};

static void spacemit_pctrl_dbg_show(struct pinctrl_dev *pctldev,
        struct seq_file *seq, unsigned int pin)
{
 struct spacemit_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
 const struct spacemit_pin *spin = spacemit_get_pin(pctrl, pin);
 enum spacemit_pin_io_type type = spacemit_to_pin_io_type(spin);
 void __iomem *reg;
 u32 value;

 seq_printf(seq, "offset: 0x%04x ", spacemit_pin_to_offset(pin));
 seq_printf(seq, "type: %s ", io_type_desc[type]);

 reg = spacemit_pin_to_reg(pctrl, pin);
 value = readl(reg);
 seq_printf(seq, "mux: %ld reg: 0x%04x", (value & PAD_MUX), value);
}

/* use IO high level output current as the table */
static struct spacemit_pin_drv_strength spacemit_ds_1v8_tbl[4] = {
 { 0, 11 },
 { 2, 21 },
 { 4, 32 },
 { 6, 42 },
};

static struct spacemit_pin_drv_strength spacemit_ds_3v3_tbl[8] = {
 { 0,  7 },
 { 2, 10 },
 { 4, 13 },
 { 6, 16 },
 { 1, 19 },
 { 3, 23 },
 { 5, 26 },
 { 7, 29 },
};

static inline u8 spacemit_get_ds_value(struct spacemit_pin_drv_strength *tbl,
           u32 num, u32 mA)
{
 int i;

 for (i = 0; i < num; i++)
  if (mA <= tbl[i].mA)
   return tbl[i].val;

 return tbl[num - 1].val;
}

static inline u32 spacemit_get_ds_mA(struct spacemit_pin_drv_strength *tbl,
         u32 num, u32 val)
{
 int i;

 for (i = 0; i < num; i++)
  if (val == tbl[i].val)
   return tbl[i].mA;

 return 0;
}

static inline u8 spacemit_get_driver_strength(enum spacemit_pin_io_type type,
           u32 mA)
{
 switch (type) {
 case IO_TYPE_1V8:
  return spacemit_get_ds_value(spacemit_ds_1v8_tbl,
          ARRAY_SIZE(spacemit_ds_1v8_tbl),
          mA);
 case IO_TYPE_3V3:
  return spacemit_get_ds_value(spacemit_ds_3v3_tbl,
          ARRAY_SIZE(spacemit_ds_3v3_tbl),
          mA);
 default:
  return 0;
 }
}

static inline u32 spacemit_get_drive_strength_mA(enum spacemit_pin_io_type type,
       u32 value)
{
 switch (type) {
 case IO_TYPE_1V8:
  return spacemit_get_ds_mA(spacemit_ds_1v8_tbl,
       ARRAY_SIZE(spacemit_ds_1v8_tbl),
       value & 0x6);
 case IO_TYPE_3V3:
  return spacemit_get_ds_mA(spacemit_ds_3v3_tbl,
       ARRAY_SIZE(spacemit_ds_3v3_tbl),
       value);
 default:
  return 0;
 }
}

static int spacemit_pctrl_check_power(struct pinctrl_dev *pctldev,
          struct device_node *dn,
          struct spacemit_pin_mux_config *pinmuxs,
          int num_pins, const char *grpname)
{
 struct spacemit_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
 struct device *dev = pctrl->dev;
 enum spacemit_pin_io_type type;
 u32 power = 0, i;

 of_property_read_u32(dn, "power-source", &power);

 for (i = 0; i < num_pins; i++) {
  type = spacemit_to_pin_io_type(pinmuxs[i].pin);

  if (type != IO_TYPE_EXTERNAL)
   continue;

  switch (power) {
  case PIN_POWER_STATE_1V8:
  case PIN_POWER_STATE_3V3:
   break;
  default:
   dev_err(dev, "group %s has unsupported power\n",
    grpname);
   return -ENOTSUPP;
  }
 }

 return 0;
}

static int spacemit_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
      struct device_node *np,
      struct pinctrl_map **maps,
      unsigned int *num_maps)
{
 struct spacemit_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
 struct device *dev = pctrl->dev;
 struct device_node *child;
 struct pinctrl_map *map;
 const char **grpnames;
 const char *grpname;
 int ngroups = 0;
 int nmaps = 0;
 int ret;

 for_each_available_child_of_node(np, child)
  ngroups += 1;

 grpnames = devm_kcalloc(dev, ngroups, sizeof(*grpnames), GFP_KERNEL);
 if (!grpnames)
  return -ENOMEM;

 map = kcalloc(ngroups * 2, sizeof(*map), GFP_KERNEL);
 if (!map)
  return -ENOMEM;

 ngroups = 0;
 guard(mutex)(&pctrl->mutex);
 for_each_available_child_of_node_scoped(np, child) {
  struct spacemit_pin_mux_config *pinmuxs;
  unsigned int config, *pins;
  int i, npins;

  npins = of_property_count_u32_elems(child, "pinmux");

  if (npins < 1) {
   dev_err(dev, "invalid pinctrl group %pOFn.%pOFn\n",
    np, child);
   return -EINVAL;
  }

  grpname = devm_kasprintf(dev, GFP_KERNEL, "%pOFn.%pOFn",
      np, child);
  if (!grpname)
   return -ENOMEM;

  grpnames[ngroups++] = grpname;

  pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
  if (!pins)
   return -ENOMEM;

  pinmuxs = devm_kcalloc(dev, npins, sizeof(*pinmuxs), GFP_KERNEL);
  if (!pinmuxs)
   return -ENOMEM;

  for (i = 0; i < npins; i++) {
   ret = of_property_read_u32_index(child, "pinmux",
        i, &config);

   if (ret)
    return -EINVAL;

   pins[i] = spacemit_dt_get_pin(config);
   pinmuxs[i].config = config;
   pinmuxs[i].pin = spacemit_get_pin(pctrl, pins[i]);

   if (!pinmuxs[i].pin)
    return dev_err_probe(dev, -ENODEV, "failed to get pin %d\n", pins[i]);
  }

  ret = spacemit_pctrl_check_power(pctldev, child, pinmuxs,
       npins, grpname);
  if (ret < 0)
   return ret;

  map[nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
  map[nmaps].data.mux.function = np->name;
  map[nmaps].data.mux.group = grpname;
  nmaps += 1;

  ret = pinctrl_generic_add_group(pctldev, grpname,
      pins, npins, pinmuxs);
  if (ret < 0)
   return dev_err_probe(dev, ret, "failed to add group %s: %d\n", grpname, ret);

  ret = pinconf_generic_parse_dt_config(child, pctldev,
            &map[nmaps].data.configs.configs,
            &map[nmaps].data.configs.num_configs);
  if (ret)
   return dev_err_probe(dev, ret, "failed to parse pin config of group %s\n",
    grpname);

  if (map[nmaps].data.configs.num_configs == 0)
   continue;

  map[nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
  map[nmaps].data.configs.group_or_pin = grpname;
  nmaps += 1;
 }

 ret = pinmux_generic_add_function(pctldev, np->name,
       grpnames, ngroups, NULL);
 if (ret < 0) {
  pinctrl_utils_free_map(pctldev, map, nmaps);
  return dev_err_probe(dev, ret, "error adding function %s\n", np->name);
 }

 *maps = map;
 *num_maps = nmaps;

 return 0;
}

static const struct pinctrl_ops spacemit_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  = spacemit_pctrl_dbg_show,
 .dt_node_to_map  = spacemit_pctrl_dt_node_to_map,
 .dt_free_map  = pinctrl_utils_free_map,
};

static int spacemit_pmx_set_mux(struct pinctrl_dev *pctldev,
    unsigned int fsel, unsigned int gsel)
{
 struct spacemit_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
 const struct group_desc *group;
 const struct spacemit_pin_mux_config *configs;
 unsigned int i, mux;
 void __iomem *reg;

 group = pinctrl_generic_get_group(pctldev, gsel);
 if (!group)
  return -EINVAL;

 configs = group->data;

 for (i = 0; i < group->grp.npins; i++) {
  const struct spacemit_pin *spin = configs[i].pin;
  u32 value = configs[i].config;

  reg = spacemit_pin_to_reg(pctrl, spin->pin);
  mux = spacemit_dt_get_pin_mux(value);

  guard(raw_spinlock_irqsave)(&pctrl->lock);
  value = readl_relaxed(reg) & ~PAD_MUX;
  writel_relaxed(mux | value, reg);
 }

 return 0;
}

static int spacemit_request_gpio(struct pinctrl_dev *pctldev,
     struct pinctrl_gpio_range *range,
     unsigned int pin)
{
 struct spacemit_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
 const struct spacemit_pin *spin = spacemit_get_pin(pctrl, pin);
 void __iomem *reg;

 reg = spacemit_pin_to_reg(pctrl, pin);
 guard(raw_spinlock_irqsave)(&pctrl->lock);
 writel_relaxed(spin->gpiofunc, reg);

 return 0;
}

static const struct pinmux_ops spacemit_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  = spacemit_pmx_set_mux,
 .gpio_request_enable = spacemit_request_gpio,
 .strict   = true,
};

static int spacemit_pinconf_get(struct pinctrl_dev *pctldev,
    unsigned int pin, unsigned long *config)
{
 struct spacemit_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
 int param = pinconf_to_config_param(*config);
 u32 value, arg = 0;

 if (!pin)
  return -EINVAL;

 value = readl(spacemit_pin_to_reg(pctrl, pin));

 switch (param) {
 case PIN_CONFIG_SLEW_RATE:
  if (FIELD_GET(PAD_SLEW_RATE_EN, value))
   arg = FIELD_GET(PAD_SLEW_RATE, value) + 2;
  else
   arg = 0;
  break;
 default:
  return -EINVAL;
 }

 *config = pinconf_to_config_packed(param, arg);

 return 0;
}

#define ENABLE_DRV_STRENGTH BIT(1)
#define ENABLE_SLEW_RATE BIT(2)
static int spacemit_pinconf_generate_config(const struct spacemit_pin *spin,
         unsigned long *configs,
         unsigned int num_configs,
         u32 *value)
{
 enum spacemit_pin_io_type type;
 int i, param;
 u32 v = 0, voltage = 0, arg, val;
 u32 flag = 0, drv_strength, slew_rate;

 if (!spin)
  return -EINVAL;

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

  switch (param) {
  case PIN_CONFIG_BIAS_DISABLE:
   v &= ~(PAD_PULL_EN | PAD_PULLDOWN | PAD_PULLUP);
   v &= ~PAD_STRONG_PULL;
   break;
  case PIN_CONFIG_BIAS_PULL_DOWN:
   v &= ~(PAD_PULLUP | PAD_STRONG_PULL);
   v |= (PAD_PULL_EN | PAD_PULLDOWN);
   break;
  case PIN_CONFIG_BIAS_PULL_UP:
   v &= ~PAD_PULLDOWN;
   v |= (PAD_PULL_EN | PAD_PULLUP);

   if (arg == 1)
    v |= PAD_STRONG_PULL;
   break;
  case PIN_CONFIG_DRIVE_STRENGTH:
   flag |= ENABLE_DRV_STRENGTH;
   drv_strength = arg;
   break;
  case PIN_CONFIG_INPUT_SCHMITT:
   v &= ~PAD_SCHMITT;
   v |= FIELD_PREP(PAD_SCHMITT, arg);
   break;
  case PIN_CONFIG_POWER_SOURCE:
   voltage = arg;
   break;
  case PIN_CONFIG_SLEW_RATE:
   if (arg) {
    flag |= ENABLE_SLEW_RATE;
    v |= PAD_SLEW_RATE_EN;
    slew_rate = arg;
   } else {
    v &= ~PAD_SLEW_RATE_EN;
   }
   break;
  default:
   return -EINVAL;
  }
 }

 if (flag & ENABLE_DRV_STRENGTH) {
  type = spacemit_to_pin_io_type(spin);

  /* fix external io type */
  if (type == IO_TYPE_EXTERNAL) {
   switch (voltage) {
   case 1800:
    type = IO_TYPE_1V8;
    break;
   case 3300:
    type = IO_TYPE_3V3;
    break;
   default:
    return -EINVAL;
   }
  }

  val = spacemit_get_driver_strength(type, drv_strength);

  v &= ~PAD_DRIVE;
  v |= FIELD_PREP(PAD_DRIVE, val);
 }

 if (flag & ENABLE_SLEW_RATE) {
  /* check, driver strength & slew rate */
  if (flag & ENABLE_DRV_STRENGTH) {
   val = FIELD_GET(PAD_SLEW_RATE, v) + 2;
   if (slew_rate > 1 && slew_rate != val) {
    pr_err("slew rate conflict with drive strength\n");
    return -EINVAL;
   }
  } else {
   v &= ~PAD_SLEW_RATE;
   slew_rate = slew_rate > 1 ? (slew_rate - 2) : 0;
   v |= FIELD_PREP(PAD_SLEW_RATE, slew_rate);
  }
 }

 *value = v;

 return 0;
}

static int spacemit_pin_set_config(struct spacemit_pinctrl *pctrl,
       unsigned int pin, u32 value)
{
 const struct spacemit_pin *spin = spacemit_get_pin(pctrl, pin);
 void __iomem *reg;
 unsigned int mux;

 if (!pin)
  return -EINVAL;

 reg = spacemit_pin_to_reg(pctrl, spin->pin);

 guard(raw_spinlock_irqsave)(&pctrl->lock);
 mux = readl_relaxed(reg) & PAD_MUX;
 writel_relaxed(mux | value, reg);

 return 0;
}

static int spacemit_pinconf_set(struct pinctrl_dev *pctldev,
    unsigned int pin, unsigned long *configs,
    unsigned int num_configs)
{
 struct spacemit_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
 const struct spacemit_pin *spin = spacemit_get_pin(pctrl, pin);
 u32 value;

 if (spacemit_pinconf_generate_config(spin, configs, num_configs, &value))
  return -EINVAL;

 return spacemit_pin_set_config(pctrl, pin, value);
}

static int spacemit_pinconf_group_set(struct pinctrl_dev *pctldev,
          unsigned int gsel,
          unsigned long *configs,
          unsigned int num_configs)
{
 struct spacemit_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
 const struct spacemit_pin *spin;
 const struct group_desc *group;
 u32 value;
 int i;

 group = pinctrl_generic_get_group(pctldev, gsel);
 if (!group)
  return -EINVAL;

 spin = spacemit_get_pin(pctrl, group->grp.pins[0]);
 if (spacemit_pinconf_generate_config(spin, configs, num_configs, &value))
  return -EINVAL;

 for (i = 0; i < group->grp.npins; i++)
  spacemit_pin_set_config(pctrl, group->grp.pins[i], value);

 return 0;
}

static void spacemit_pinconf_dbg_pull(struct seq_file *seq, unsigned int value)
{
 u32 normal, strong;

 if (!FIELD_GET(PAD_PULL_EN, value)) {
  seq_puts(seq, ", bias pull disabled");
  return;
 }

 if (FIELD_GET(PAD_PULLDOWN, value))
  seq_puts(seq, ", bias pull down");

 normal = FIELD_GET(PAD_PULLUP, value);
 strong = FIELD_GET(PAD_STRONG_PULL, value);

 if (normal && strong)
  seq_puts(seq, ", bias strong pull up");
 else if (normal)
  seq_puts(seq, ", bias normal pull up");
}

static void spacemit_pinconf_dbg_show(struct pinctrl_dev *pctldev,
          struct seq_file *seq, unsigned int pin)
{
 struct spacemit_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
 const struct spacemit_pin *spin = spacemit_get_pin(pctrl, pin);
 enum spacemit_pin_io_type type = spacemit_to_pin_io_type(spin);
 void __iomem *reg = spacemit_pin_to_reg(pctrl, pin);
 u32 value, tmp, mA;

 value = readl(reg);
 spacemit_pinconf_dbg_pull(seq, value);

 seq_printf(seq, ", io type (%s)", io_type_desc[type]);

 tmp = FIELD_GET(PAD_DRIVE, value);
 if (type == IO_TYPE_1V8 || type == IO_TYPE_3V3) {
  mA = spacemit_get_drive_strength_mA(type, tmp);
  seq_printf(seq, ", drive strength (%d mA)", mA);
 }

 /* drive strength depend on power source, so show all values */
 if (type == IO_TYPE_EXTERNAL)
  seq_printf(seq, ", drive strength (%d or %d mA)",
      spacemit_get_drive_strength_mA(IO_TYPE_1V8, tmp),
      spacemit_get_drive_strength_mA(IO_TYPE_3V3, tmp));

 seq_printf(seq, ", register (0x%04x)\n", value);
}

static const struct pinconf_ops spacemit_pinconf_ops = {
 .pin_config_get   = spacemit_pinconf_get,
 .pin_config_set   = spacemit_pinconf_set,
 .pin_config_group_set  = spacemit_pinconf_group_set,
 .pin_config_dbg_show  = spacemit_pinconf_dbg_show,
 .is_generic   = true,
};

static int spacemit_pinctrl_probe(struct platform_device *pdev)
{
 struct device *dev = &pdev->dev;
 struct spacemit_pinctrl *pctrl;
 struct clk *func_clk, *bus_clk;
 const struct spacemit_pinctrl_data *pctrl_data;
 int ret;

 pctrl_data = device_get_match_data(dev);
 if (!pctrl_data)
  return -ENODEV;

 if (pctrl_data->npins == 0)
  return dev_err_probe(dev, -EINVAL, "invalid pin data\n");

 pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL);
 if (!pctrl)
  return -ENOMEM;

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

 func_clk = devm_clk_get_enabled(dev, "func");
 if (IS_ERR(func_clk))
  return dev_err_probe(dev, PTR_ERR(func_clk), "failed to get func clock\n");

 bus_clk = devm_clk_get_enabled(dev, "bus");
 if (IS_ERR(bus_clk))
  return dev_err_probe(dev, PTR_ERR(bus_clk), "failed to get bus clock\n");

 pctrl->pdesc.name = dev_name(dev);
 pctrl->pdesc.pins = pctrl_data->pins;
 pctrl->pdesc.npins = pctrl_data->npins;
 pctrl->pdesc.pctlops = &spacemit_pctrl_ops;
 pctrl->pdesc.pmxops = &spacemit_pmx_ops;
 pctrl->pdesc.confops = &spacemit_pinconf_ops;
 pctrl->pdesc.owner = THIS_MODULE;

 pctrl->data = pctrl_data;
 pctrl->dev = dev;
 raw_spin_lock_init(&pctrl->lock);

 ret = devm_mutex_init(dev, &pctrl->mutex);
 if (ret)
  return ret;

 platform_set_drvdata(pdev, pctrl);

 ret = devm_pinctrl_register_and_init(dev, &pctrl->pdesc,
          pctrl, &pctrl->pctl_dev);
 if (ret)
  return dev_err_probe(dev, ret,
         "fail to register pinctrl driver\n");

 return pinctrl_enable(pctrl->pctl_dev);
}

static const struct pinctrl_pin_desc k1_pin_desc[] = {
 PINCTRL_PIN(0, "GPIO_00"),
 PINCTRL_PIN(1, "GPIO_01"),
 PINCTRL_PIN(2, "GPIO_02"),
 PINCTRL_PIN(3, "GPIO_03"),
 PINCTRL_PIN(4, "GPIO_04"),
 PINCTRL_PIN(5, "GPIO_05"),
 PINCTRL_PIN(6, "GPIO_06"),
 PINCTRL_PIN(7, "GPIO_07"),
 PINCTRL_PIN(8, "GPIO_08"),
 PINCTRL_PIN(9, "GPIO_09"),
 PINCTRL_PIN(10, "GPIO_10"),
 PINCTRL_PIN(11, "GPIO_11"),
 PINCTRL_PIN(12, "GPIO_12"),
 PINCTRL_PIN(13, "GPIO_13"),
 PINCTRL_PIN(14, "GPIO_14"),
 PINCTRL_PIN(15, "GPIO_15"),
 PINCTRL_PIN(16, "GPIO_16"),
 PINCTRL_PIN(17, "GPIO_17"),
 PINCTRL_PIN(18, "GPIO_18"),
 PINCTRL_PIN(19, "GPIO_19"),
 PINCTRL_PIN(20, "GPIO_20"),
 PINCTRL_PIN(21, "GPIO_21"),
 PINCTRL_PIN(22, "GPIO_22"),
 PINCTRL_PIN(23, "GPIO_23"),
 PINCTRL_PIN(24, "GPIO_24"),
 PINCTRL_PIN(25, "GPIO_25"),
 PINCTRL_PIN(26, "GPIO_26"),
 PINCTRL_PIN(27, "GPIO_27"),
 PINCTRL_PIN(28, "GPIO_28"),
 PINCTRL_PIN(29, "GPIO_29"),
 PINCTRL_PIN(30, "GPIO_30"),
 PINCTRL_PIN(31, "GPIO_31"),
 PINCTRL_PIN(32, "GPIO_32"),
 PINCTRL_PIN(33, "GPIO_33"),
 PINCTRL_PIN(34, "GPIO_34"),
 PINCTRL_PIN(35, "GPIO_35"),
 PINCTRL_PIN(36, "GPIO_36"),
 PINCTRL_PIN(37, "GPIO_37"),
 PINCTRL_PIN(38, "GPIO_38"),
 PINCTRL_PIN(39, "GPIO_39"),
 PINCTRL_PIN(40, "GPIO_40"),
 PINCTRL_PIN(41, "GPIO_41"),
 PINCTRL_PIN(42, "GPIO_42"),
 PINCTRL_PIN(43, "GPIO_43"),
 PINCTRL_PIN(44, "GPIO_44"),
 PINCTRL_PIN(45, "GPIO_45"),
 PINCTRL_PIN(46, "GPIO_46"),
 PINCTRL_PIN(47, "GPIO_47"),
 PINCTRL_PIN(48, "GPIO_48"),
 PINCTRL_PIN(49, "GPIO_49"),
 PINCTRL_PIN(50, "GPIO_50"),
 PINCTRL_PIN(51, "GPIO_51"),
 PINCTRL_PIN(52, "GPIO_52"),
 PINCTRL_PIN(53, "GPIO_53"),
 PINCTRL_PIN(54, "GPIO_54"),
 PINCTRL_PIN(55, "GPIO_55"),
 PINCTRL_PIN(56, "GPIO_56"),
 PINCTRL_PIN(57, "GPIO_57"),
 PINCTRL_PIN(58, "GPIO_58"),
 PINCTRL_PIN(59, "GPIO_59"),
 PINCTRL_PIN(60, "GPIO_60"),
 PINCTRL_PIN(61, "GPIO_61"),
 PINCTRL_PIN(62, "GPIO_62"),
 PINCTRL_PIN(63, "GPIO_63"),
 PINCTRL_PIN(64, "GPIO_64"),
 PINCTRL_PIN(65, "GPIO_65"),
 PINCTRL_PIN(66, "GPIO_66"),
 PINCTRL_PIN(67, "GPIO_67"),
 PINCTRL_PIN(68, "GPIO_68"),
 PINCTRL_PIN(69, "GPIO_69"),
 PINCTRL_PIN(70, "GPIO_70/PRI_DTI"),
 PINCTRL_PIN(71, "GPIO_71/PRI_TMS"),
 PINCTRL_PIN(72, "GPIO_72/PRI_TCK"),
 PINCTRL_PIN(73, "GPIO_73/PRI_TDO"),
 PINCTRL_PIN(74, "GPIO_74"),
 PINCTRL_PIN(75, "GPIO_75"),
 PINCTRL_PIN(76, "GPIO_76"),
 PINCTRL_PIN(77, "GPIO_77"),
 PINCTRL_PIN(78, "GPIO_78"),
 PINCTRL_PIN(79, "GPIO_79"),
 PINCTRL_PIN(80, "GPIO_80"),
 PINCTRL_PIN(81, "GPIO_81"),
 PINCTRL_PIN(82, "GPIO_82"),
 PINCTRL_PIN(83, "GPIO_83"),
 PINCTRL_PIN(84, "GPIO_84"),
 PINCTRL_PIN(85, "GPIO_85"),
 PINCTRL_PIN(86, "GPIO_86"),
 PINCTRL_PIN(87, "GPIO_87"),
 PINCTRL_PIN(88, "GPIO_88"),
 PINCTRL_PIN(89, "GPIO_89"),
 PINCTRL_PIN(90, "GPIO_90"),
 PINCTRL_PIN(91, "GPIO_91"),
 PINCTRL_PIN(92, "GPIO_92"),
 PINCTRL_PIN(93, "GPIO_93/PWR_SCL"),
 PINCTRL_PIN(94, "GPIO_94/PWR_SDA"),
 PINCTRL_PIN(95, "GPIO_95/VCX0_EN"),
 PINCTRL_PIN(96, "GPIO_96/DVL0"),
 PINCTRL_PIN(97, "GPIO_97/DVL1"),
 PINCTRL_PIN(98,  "GPIO_98/QSPI_DAT3"),
 PINCTRL_PIN(99,  "GPIO_99/QSPI_DAT2"),
 PINCTRL_PIN(100, "GPIO_100/QSPI_DAT1"),
 PINCTRL_PIN(101, "GPIO_101/QSPI_DAT0"),
 PINCTRL_PIN(102, "GPIO_102/QSPI_CLK"),
 PINCTRL_PIN(103, "GPIO_103/QSPI_CS1"),
 PINCTRL_PIN(104, "GPIO_104/MMC1_DAT3"),
 PINCTRL_PIN(105, "GPIO_105/MMC1_DAT2"),
 PINCTRL_PIN(106, "GPIO_106/MMC1_DAT1"),
 PINCTRL_PIN(107, "GPIO_107/MMC1_DAT0"),
 PINCTRL_PIN(108, "GPIO_108/MMC1_CMD"),
 PINCTRL_PIN(109, "GPIO_109/MMC1_CLK"),
 PINCTRL_PIN(110, "GPIO_110"),
 PINCTRL_PIN(111, "GPIO_111"),
 PINCTRL_PIN(112, "GPIO_112"),
 PINCTRL_PIN(113, "GPIO_113"),
 PINCTRL_PIN(114, "GPIO_114"),
 PINCTRL_PIN(115, "GPIO_115"),
 PINCTRL_PIN(116, "GPIO_116"),
 PINCTRL_PIN(117, "GPIO_117"),
 PINCTRL_PIN(118, "GPIO_118"),
 PINCTRL_PIN(119, "GPIO_119"),
 PINCTRL_PIN(120, "GPIO_120"),
 PINCTRL_PIN(121, "GPIO_121"),
 PINCTRL_PIN(122, "GPIO_122"),
 PINCTRL_PIN(123, "GPIO_123"),
 PINCTRL_PIN(124, "GPIO_124"),
 PINCTRL_PIN(125, "GPIO_125"),
 PINCTRL_PIN(126, "GPIO_126"),
 PINCTRL_PIN(127, "GPIO_127"),
};

static const struct spacemit_pin k1_pin_data[ARRAY_SIZE(k1_pin_desc)] = {
 K1_FUNC_PIN(0, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(1, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(2, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(3, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(4, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(5, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(6, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(7, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(8, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(9, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(10, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(11, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(12, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(13, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(14, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(15, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(16, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(17, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(18, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(19, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(20, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(21, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(22, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(23, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(24, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(25, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(26, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(27, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(28, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(29, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(30, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(31, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(32, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(33, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(34, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(35, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(36, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(37, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(38, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(39, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(40, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(41, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(42, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(43, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(44, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(45, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(46, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(47, 0, IO_TYPE_EXTERNAL),
 K1_FUNC_PIN(48, 0, IO_TYPE_EXTERNAL),
 K1_FUNC_PIN(49, 0, IO_TYPE_EXTERNAL),
 K1_FUNC_PIN(50, 0, IO_TYPE_EXTERNAL),
 K1_FUNC_PIN(51, 0, IO_TYPE_EXTERNAL),
 K1_FUNC_PIN(52, 0, IO_TYPE_EXTERNAL),
 K1_FUNC_PIN(53, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(54, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(55, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(56, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(57, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(58, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(59, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(60, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(61, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(62, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(63, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(64, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(65, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(66, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(67, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(68, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(69, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(70, 1, IO_TYPE_1V8),
 K1_FUNC_PIN(71, 1, IO_TYPE_1V8),
 K1_FUNC_PIN(72, 1, IO_TYPE_1V8),
 K1_FUNC_PIN(73, 1, IO_TYPE_1V8),
 K1_FUNC_PIN(74, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(75, 0, IO_TYPE_EXTERNAL),
 K1_FUNC_PIN(76, 0, IO_TYPE_EXTERNAL),
 K1_FUNC_PIN(77, 0, IO_TYPE_EXTERNAL),
 K1_FUNC_PIN(78, 0, IO_TYPE_EXTERNAL),
 K1_FUNC_PIN(79, 0, IO_TYPE_EXTERNAL),
 K1_FUNC_PIN(80, 0, IO_TYPE_EXTERNAL),
 K1_FUNC_PIN(81, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(82, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(83, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(84, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(85, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(86, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(87, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(88, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(89, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(90, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(91, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(92, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(93, 1, IO_TYPE_1V8),
 K1_FUNC_PIN(94, 1, IO_TYPE_1V8),
 K1_FUNC_PIN(95, 1, IO_TYPE_1V8),
 K1_FUNC_PIN(96, 1, IO_TYPE_1V8),
 K1_FUNC_PIN(97, 1, IO_TYPE_1V8),
 K1_FUNC_PIN(98, 1, IO_TYPE_EXTERNAL),
 K1_FUNC_PIN(99, 1, IO_TYPE_EXTERNAL),
 K1_FUNC_PIN(100, 1, IO_TYPE_EXTERNAL),
 K1_FUNC_PIN(101, 1, IO_TYPE_EXTERNAL),
 K1_FUNC_PIN(102, 1, IO_TYPE_EXTERNAL),
 K1_FUNC_PIN(103, 1, IO_TYPE_EXTERNAL),
 K1_FUNC_PIN(104, 4, IO_TYPE_EXTERNAL),
 K1_FUNC_PIN(105, 4, IO_TYPE_EXTERNAL),
 K1_FUNC_PIN(106, 4, IO_TYPE_EXTERNAL),
 K1_FUNC_PIN(107, 4, IO_TYPE_EXTERNAL),
 K1_FUNC_PIN(108, 4, IO_TYPE_EXTERNAL),
 K1_FUNC_PIN(109, 4, IO_TYPE_EXTERNAL),
 K1_FUNC_PIN(110, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(111, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(112, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(113, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(114, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(115, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(116, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(117, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(118, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(119, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(120, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(121, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(122, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(123, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(124, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(125, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(126, 0, IO_TYPE_1V8),
 K1_FUNC_PIN(127, 0, IO_TYPE_1V8),
};

static const struct spacemit_pinctrl_data k1_pinctrl_data = {
 .pins = k1_pin_desc,
 .data = k1_pin_data,
 .npins = ARRAY_SIZE(k1_pin_desc),
};

static const struct of_device_id k1_pinctrl_ids[] = {
 { .compatible = "spacemit,k1-pinctrl", .data = &k1_pinctrl_data },
 { /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, k1_pinctrl_ids);

static struct platform_driver k1_pinctrl_driver = {
 .probe = spacemit_pinctrl_probe,
 .driver = {
  .name   = "k1-pinctrl",
  .suppress_bind_attrs = true,
  .of_match_table  = k1_pinctrl_ids,
 },
};
builtin_platform_driver(k1_pinctrl_driver);

MODULE_AUTHOR("Yixun Lan ");
MODULE_DESCRIPTION("Pinctrl driver for the SpacemiT K1 SoC");
MODULE_LICENSE("GPL");

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

¤ Dauer der Verarbeitung: 0.7 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.