aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/pinctrl/sophgo/pinctrl-cv18xx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pinctrl/sophgo/pinctrl-cv18xx.c')
-rw-r--r--drivers/pinctrl/sophgo/pinctrl-cv18xx.c602
1 files changed, 144 insertions, 458 deletions
diff --git a/drivers/pinctrl/sophgo/pinctrl-cv18xx.c b/drivers/pinctrl/sophgo/pinctrl-cv18xx.c
index 57f2674e75d6..c3a2dcf71f2a 100644
--- a/drivers/pinctrl/sophgo/pinctrl-cv18xx.c
+++ b/drivers/pinctrl/sophgo/pinctrl-cv18xx.c
@@ -15,8 +15,6 @@
#include <linux/seq_file.h>
#include <linux/spinlock.h>
-#include <linux/pinctrl/consumer.h>
-#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinctrl.h>
@@ -24,35 +22,15 @@
#include <dt-bindings/pinctrl/pinctrl-cv18xx.h>
-#include "../core.h"
#include "../pinctrl-utils.h"
-#include "../pinconf.h"
#include "../pinmux.h"
#include "pinctrl-cv18xx.h"
-struct cv1800_pinctrl {
- struct device *dev;
- struct pinctrl_dev *pctl_dev;
- const struct cv1800_pinctrl_data *data;
- struct pinctrl_desc pdesc;
+struct cv1800_priv {
u32 *power_cfg;
-
- struct mutex mutex;
- raw_spinlock_t lock;
-
void __iomem *regs[2];
};
-struct cv1800_pin_mux_config {
- struct cv1800_pin *pin;
- u32 config;
-};
-
-static unsigned int cv1800_dt_get_pin(u32 value)
-{
- return value & GENMASK(15, 0);
-}
-
static unsigned int cv1800_dt_get_pin_mux(u32 value)
{
return (value >> 16) & GENMASK(7, 0);
@@ -66,40 +44,28 @@ static unsigned int cv1800_dt_get_pin_mux2(u32 value)
#define cv1800_pinctrl_get_component_addr(pctrl, _comp) \
((pctrl)->regs[(_comp)->area] + (_comp)->offset)
-static int cv1800_cmp_pin(const void *key, const void *pivot)
-{
- const struct cv1800_pin *pin = pivot;
- int pin_id = (long)key;
- int pivid = pin->pin;
-
- return pin_id - pivid;
-}
-
-static int cv1800_set_power_cfg(struct cv1800_pinctrl *pctrl,
+static int cv1800_set_power_cfg(struct sophgo_pinctrl *pctrl,
u8 domain, u32 cfg)
{
- if (domain >= pctrl->data->npd)
+ struct cv1800_priv *priv = pctrl->priv_ctrl;
+
+ if (domain >= pctrl->data->npds)
return -ENOTSUPP;
- if (pctrl->power_cfg[domain] && pctrl->power_cfg[domain] != cfg)
+ if (priv->power_cfg[domain] && priv->power_cfg[domain] != cfg)
return -EINVAL;
- pctrl->power_cfg[domain] = cfg;
+ priv->power_cfg[domain] = cfg;
return 0;
}
-static int cv1800_get_power_cfg(struct cv1800_pinctrl *pctrl,
+static int cv1800_get_power_cfg(struct sophgo_pinctrl *pctrl,
u8 domain)
{
- return pctrl->power_cfg[domain];
-}
+ struct cv1800_priv *priv = pctrl->priv_ctrl;
-static struct cv1800_pin *cv1800_get_pin(struct cv1800_pinctrl *pctrl,
- unsigned long pin)
-{
- return bsearch((void *)pin, pctrl->data->pindata, pctrl->data->npins,
- sizeof(struct cv1800_pin), cv1800_cmp_pin);
+ return priv->power_cfg[domain];
}
#define PIN_BGA_ID_OFFSET 8
@@ -112,7 +78,7 @@ static const char *const io_type_desc[] = {
"ETH"
};
-static const char *cv1800_get_power_cfg_desc(struct cv1800_pinctrl *pctrl,
+static const char *cv1800_get_power_cfg_desc(struct sophgo_pinctrl *pctrl,
u8 domain)
{
return pctrl->data->pdnames[domain];
@@ -121,53 +87,57 @@ static const char *cv1800_get_power_cfg_desc(struct cv1800_pinctrl *pctrl,
static void cv1800_pctrl_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *seq, unsigned int pin_id)
{
- struct cv1800_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
- struct cv1800_pin *pin = cv1800_get_pin(pctrl, pin_id);
+ struct sophgo_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+ struct cv1800_priv *priv = pctrl->priv_ctrl;
+ const struct sophgo_pin *sp = sophgo_get_pin(pctrl, pin_id);
+ const struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
enum cv1800_pin_io_type type = cv1800_pin_io_type(pin);
+ u32 pin_hwid = pin->pin.id;
u32 value;
void __iomem *reg;
- if (pin->pin >> PIN_BGA_ID_OFFSET)
+ if (pin_hwid >> PIN_BGA_ID_OFFSET)
seq_printf(seq, "pos: %c%u ",
- 'A' + (pin->pin >> PIN_BGA_ID_OFFSET) - 1,
- pin->pin & PIN_BGA_ID_MASK);
+ 'A' + (pin_hwid >> PIN_BGA_ID_OFFSET) - 1,
+ pin_hwid & PIN_BGA_ID_MASK);
else
- seq_printf(seq, "pos: %u ", pin->pin);
+ seq_printf(seq, "pos: %u ", pin_hwid);
seq_printf(seq, "power-domain: %s ",
cv1800_get_power_cfg_desc(pctrl, pin->power_domain));
seq_printf(seq, "type: %s ", io_type_desc[type]);
- reg = cv1800_pinctrl_get_component_addr(pctrl, &pin->mux);
+ reg = cv1800_pinctrl_get_component_addr(priv, &pin->mux);
value = readl(reg);
seq_printf(seq, "mux: 0x%08x ", value);
- if (pin->flags & CV1800_PIN_HAVE_MUX2) {
- reg = cv1800_pinctrl_get_component_addr(pctrl, &pin->mux2);
+ if (pin->pin.flags & CV1800_PIN_HAVE_MUX2) {
+ reg = cv1800_pinctrl_get_component_addr(priv, &pin->mux2);
value = readl(reg);
seq_printf(seq, "mux2: 0x%08x ", value);
}
if (type == IO_TYPE_1V8_ONLY || type == IO_TYPE_1V8_OR_3V3) {
- reg = cv1800_pinctrl_get_component_addr(pctrl, &pin->conf);
+ reg = cv1800_pinctrl_get_component_addr(priv, &pin->conf);
value = readl(reg);
seq_printf(seq, "conf: 0x%08x ", value);
}
}
-static int cv1800_verify_pinmux_config(const struct cv1800_pin_mux_config *config)
+static int cv1800_verify_pinmux_config(const struct sophgo_pin_mux_config *config)
{
+ struct cv1800_pin *pin = sophgo_to_cv1800_pin(config->pin);
unsigned int mux = cv1800_dt_get_pin_mux(config->config);
unsigned int mux2 = cv1800_dt_get_pin_mux2(config->config);
- if (mux > config->pin->mux.max)
+ if (mux > pin->mux.max)
return -EINVAL;
- if (config->pin->flags & CV1800_PIN_HAVE_MUX2) {
- if (mux != config->pin->mux2.pfunc)
+ if (pin->pin.flags & CV1800_PIN_HAVE_MUX2) {
+ if (mux != pin->mux2.pfunc)
return -EINVAL;
- if (mux2 > config->pin->mux2.max)
+ if (mux2 > pin->mux2.max)
return -EINVAL;
} else {
if (mux2 != PIN_MUX_INVALD)
@@ -177,9 +147,10 @@ static int cv1800_verify_pinmux_config(const struct cv1800_pin_mux_config *confi
return 0;
}
-static int cv1800_verify_pin_group(const struct cv1800_pin_mux_config *mux,
- unsigned long npins)
+static int cv1800_verify_pin_group(const struct sophgo_pin_mux_config *mux,
+ unsigned int npins)
{
+ struct cv1800_pin *pin;
enum cv1800_pin_io_type type;
u8 power_domain;
int i;
@@ -187,232 +158,78 @@ static int cv1800_verify_pin_group(const struct cv1800_pin_mux_config *mux,
if (npins == 1)
return 0;
- type = cv1800_pin_io_type(mux[0].pin);
- power_domain = mux[0].pin->power_domain;
+ pin = sophgo_to_cv1800_pin(mux[0].pin);
+ type = cv1800_pin_io_type(pin);
+ power_domain = pin->power_domain;
for (i = 0; i < npins; i++) {
- if (type != cv1800_pin_io_type(mux[i].pin) ||
- power_domain != mux[i].pin->power_domain)
+ pin = sophgo_to_cv1800_pin(mux[i].pin);
+
+ if (type != cv1800_pin_io_type(pin) ||
+ power_domain != pin->power_domain)
return -ENOTSUPP;
}
return 0;
}
-static int cv1800_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
- struct device_node *np,
- struct pinctrl_map **maps,
- unsigned int *num_maps)
+static int cv1800_dt_node_to_map_post(struct device_node *cur,
+ struct sophgo_pinctrl *pctrl,
+ struct sophgo_pin_mux_config *pinmuxs,
+ unsigned int npins)
{
- struct cv1800_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;
+ const struct cv1800_pin *pin = sophgo_to_cv1800_pin(pinmuxs[0].pin);
+ u32 power;
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;
- mutex_lock(&pctrl->mutex);
- for_each_available_child_of_node(np, child) {
- int npins = of_property_count_u32_elems(child, "pinmux");
- unsigned int *pins;
- struct cv1800_pin_mux_config *pinmuxs;
- u32 config, power;
- int i;
-
- if (npins < 1) {
- dev_err(dev, "invalid pinctrl group %pOFn.%pOFn\n",
- np, child);
- ret = -EINVAL;
- goto dt_failed;
- }
-
- grpname = devm_kasprintf(dev, GFP_KERNEL, "%pOFn.%pOFn",
- np, child);
- if (!grpname) {
- ret = -ENOMEM;
- goto dt_failed;
- }
-
- grpnames[ngroups++] = grpname;
-
- pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
- if (!pins) {
- ret = -ENOMEM;
- goto dt_failed;
- }
-
- pinmuxs = devm_kcalloc(dev, npins, sizeof(*pinmuxs), GFP_KERNEL);
- if (!pinmuxs) {
- ret = -ENOMEM;
- goto dt_failed;
- }
-
- for (i = 0; i < npins; i++) {
- ret = of_property_read_u32_index(child, "pinmux",
- i, &config);
- if (ret)
- goto dt_failed;
-
- pins[i] = cv1800_dt_get_pin(config);
- pinmuxs[i].config = config;
- pinmuxs[i].pin = cv1800_get_pin(pctrl, pins[i]);
-
- if (!pinmuxs[i].pin) {
- dev_err(dev, "failed to get pin %d\n", pins[i]);
- ret = -ENODEV;
- goto dt_failed;
- }
-
- ret = cv1800_verify_pinmux_config(&pinmuxs[i]);
- if (ret) {
- dev_err(dev, "group %s pin %d is invalid\n",
- grpname, i);
- goto dt_failed;
- }
- }
-
- ret = cv1800_verify_pin_group(pinmuxs, npins);
- if (ret) {
- dev_err(dev, "group %s is invalid\n", grpname);
- goto dt_failed;
- }
-
- ret = of_property_read_u32(child, "power-source", &power);
- if (ret)
- goto dt_failed;
-
- if (!(power == PIN_POWER_STATE_3V3 || power == PIN_POWER_STATE_1V8)) {
- dev_err(dev, "group %s have unsupported power: %u\n",
- grpname, power);
- ret = -ENOTSUPP;
- goto dt_failed;
- }
-
- ret = cv1800_set_power_cfg(pctrl, pinmuxs[0].pin->power_domain,
- power);
- if (ret)
- goto dt_failed;
-
- map[nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
- map[nmaps].data.mux.function = np->name;
- map[nmaps].data.mux.group = grpname;
- nmaps += 1;
-
- ret = pinconf_generic_parse_dt_config(child, pctldev,
- &map[nmaps].data.configs.configs,
- &map[nmaps].data.configs.num_configs);
- if (ret) {
- dev_err(dev, "failed to parse pin config of group %s: %d\n",
- grpname, ret);
- goto dt_failed;
- }
-
- ret = pinctrl_generic_add_group(pctldev, grpname,
- pins, npins, pinmuxs);
- if (ret < 0) {
- dev_err(dev, "failed to add group %s: %d\n", grpname, ret);
- goto dt_failed;
- }
-
- /* don't create a map if there are no pinconf settings */
- 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) {
- dev_err(dev, "error adding function %s: %d\n", np->name, ret);
- goto function_failed;
- }
-
- *maps = map;
- *num_maps = nmaps;
- mutex_unlock(&pctrl->mutex);
+ ret = of_property_read_u32(cur, "power-source", &power);
+ if (ret)
+ return ret;
- return 0;
+ if (!(power == PIN_POWER_STATE_3V3 || power == PIN_POWER_STATE_1V8))
+ return -ENOTSUPP;
-dt_failed:
- of_node_put(child);
-function_failed:
- pinctrl_utils_free_map(pctldev, map, nmaps);
- mutex_unlock(&pctrl->mutex);
- return ret;
+ return cv1800_set_power_cfg(pctrl, pin->power_domain, power);
}
-static const struct pinctrl_ops cv1800_pctrl_ops = {
+const struct pinctrl_ops cv1800_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 = cv1800_pctrl_dbg_show,
- .dt_node_to_map = cv1800_pctrl_dt_node_to_map,
+ .dt_node_to_map = sophgo_pctrl_dt_node_to_map,
.dt_free_map = pinctrl_utils_free_map,
};
+EXPORT_SYMBOL_GPL(cv1800_pctrl_ops);
-static int cv1800_pmx_set_mux(struct pinctrl_dev *pctldev,
- unsigned int fsel, unsigned int gsel)
+static void cv1800_set_pinmux_config(struct sophgo_pinctrl *pctrl,
+ const struct sophgo_pin *sp, u32 config)
{
- struct cv1800_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
- const struct group_desc *group;
- const struct cv1800_pin_mux_config *configs;
- unsigned int i;
-
- group = pinctrl_generic_get_group(pctldev, gsel);
- if (!group)
- return -EINVAL;
-
- configs = group->data;
-
- for (i = 0; i < group->grp.npins; i++) {
- const struct cv1800_pin *pin = configs[i].pin;
- u32 value = configs[i].config;
- void __iomem *reg_mux;
- void __iomem *reg_mux2;
- unsigned long flags;
- u32 mux;
- u32 mux2;
-
- reg_mux = cv1800_pinctrl_get_component_addr(pctrl, &pin->mux);
- reg_mux2 = cv1800_pinctrl_get_component_addr(pctrl, &pin->mux2);
- mux = cv1800_dt_get_pin_mux(value);
- mux2 = cv1800_dt_get_pin_mux2(value);
-
- raw_spin_lock_irqsave(&pctrl->lock, flags);
- writel_relaxed(mux, reg_mux);
- if (mux2 != PIN_MUX_INVALD)
- writel_relaxed(mux2, reg_mux2);
- raw_spin_unlock_irqrestore(&pctrl->lock, flags);
- }
-
- return 0;
+ const struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
+ struct cv1800_priv *priv = pctrl->priv_ctrl;
+ void __iomem *reg_mux;
+ void __iomem *reg_mux2;
+ u32 mux;
+ u32 mux2;
+
+ reg_mux = cv1800_pinctrl_get_component_addr(priv, &pin->mux);
+ reg_mux2 = cv1800_pinctrl_get_component_addr(priv, &pin->mux2);
+ mux = cv1800_dt_get_pin_mux(config);
+ mux2 = cv1800_dt_get_pin_mux2(config);
+
+ writel_relaxed(mux, reg_mux);
+ if (mux2 != PIN_MUX_INVALD)
+ writel_relaxed(mux2, reg_mux2);
}
-static const struct pinmux_ops cv1800_pmx_ops = {
+const struct pinmux_ops cv1800_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 = cv1800_pmx_set_mux,
+ .set_mux = sophgo_pmx_set_mux,
.strict = true,
};
+EXPORT_SYMBOL_GPL(cv1800_pmx_ops);
#define PIN_IO_PULLUP BIT(2)
#define PIN_IO_PULLDOWN BIT(3)
@@ -421,94 +238,14 @@ static const struct pinmux_ops cv1800_pmx_ops = {
#define PIN_IO_BUS_HOLD BIT(10)
#define PIN_IO_OUT_FAST_SLEW BIT(11)
-static u32 cv1800_pull_down_typical_resistor(struct cv1800_pinctrl *pctrl,
- struct cv1800_pin *pin)
-{
- return pctrl->data->vddio_ops->get_pull_down(pin, pctrl->power_cfg);
-}
-
-static u32 cv1800_pull_up_typical_resistor(struct cv1800_pinctrl *pctrl,
- struct cv1800_pin *pin)
-{
- return pctrl->data->vddio_ops->get_pull_up(pin, pctrl->power_cfg);
-}
-
-static int cv1800_pinctrl_oc2reg(struct cv1800_pinctrl *pctrl,
- struct cv1800_pin *pin, u32 target)
-{
- const u32 *map;
- int i, len;
-
- len = pctrl->data->vddio_ops->get_oc_map(pin, pctrl->power_cfg, &map);
- if (len < 0)
- return len;
-
- for (i = 0; i < len; i++) {
- if (map[i] >= target)
- return i;
- }
-
- return -EINVAL;
-}
-
-static int cv1800_pinctrl_reg2oc(struct cv1800_pinctrl *pctrl,
- struct cv1800_pin *pin, u32 reg)
-{
- const u32 *map;
- int len;
-
- len = pctrl->data->vddio_ops->get_oc_map(pin, pctrl->power_cfg, &map);
- if (len < 0)
- return len;
-
- if (reg >= len)
- return -EINVAL;
-
- return map[reg];
-}
-
-static int cv1800_pinctrl_schmitt2reg(struct cv1800_pinctrl *pctrl,
- struct cv1800_pin *pin, u32 target)
-{
- const u32 *map;
- int i, len;
-
- len = pctrl->data->vddio_ops->get_schmitt_map(pin, pctrl->power_cfg,
- &map);
- if (len < 0)
- return len;
-
- for (i = 0; i < len; i++) {
- if (map[i] == target)
- return i;
- }
-
- return -EINVAL;
-}
-
-static int cv1800_pinctrl_reg2schmitt(struct cv1800_pinctrl *pctrl,
- struct cv1800_pin *pin, u32 reg)
-{
- const u32 *map;
- int len;
-
- len = pctrl->data->vddio_ops->get_schmitt_map(pin, pctrl->power_cfg,
- &map);
- if (len < 0)
- return len;
-
- if (reg >= len)
- return -EINVAL;
-
- return map[reg];
-}
-
static int cv1800_pconf_get(struct pinctrl_dev *pctldev,
unsigned int pin_id, unsigned long *config)
{
- struct cv1800_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+ struct sophgo_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+ struct cv1800_priv *priv = pctrl->priv_ctrl;
int param = pinconf_to_config_param(*config);
- struct cv1800_pin *pin = cv1800_get_pin(pctrl, pin_id);
+ const struct sophgo_pin *sp = sophgo_get_pin(pctrl, pin_id);
+ const struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
enum cv1800_pin_io_type type;
u32 value;
u32 arg;
@@ -522,28 +259,28 @@ static int cv1800_pconf_get(struct pinctrl_dev *pctldev,
if (type == IO_TYPE_ETH || type == IO_TYPE_AUDIO)
return -ENOTSUPP;
- value = readl(cv1800_pinctrl_get_component_addr(pctrl, &pin->conf));
+ value = readl(cv1800_pinctrl_get_component_addr(priv, &pin->conf));
switch (param) {
case PIN_CONFIG_BIAS_PULL_DOWN:
enabled = FIELD_GET(PIN_IO_PULLDOWN, value);
- arg = cv1800_pull_down_typical_resistor(pctrl, pin);
+ arg = sophgo_pinctrl_typical_pull_down(pctrl, sp, priv->power_cfg);
break;
case PIN_CONFIG_BIAS_PULL_UP:
enabled = FIELD_GET(PIN_IO_PULLUP, value);
- arg = cv1800_pull_up_typical_resistor(pctrl, pin);
+ arg = sophgo_pinctrl_typical_pull_up(pctrl, sp, priv->power_cfg);
break;
case PIN_CONFIG_DRIVE_STRENGTH_UA:
enabled = true;
arg = FIELD_GET(PIN_IO_DRIVE, value);
- ret = cv1800_pinctrl_reg2oc(pctrl, pin, arg);
+ ret = sophgo_pinctrl_reg2oc(pctrl, sp, priv->power_cfg, arg);
if (ret < 0)
return ret;
arg = ret;
break;
case PIN_CONFIG_INPUT_SCHMITT_UV:
arg = FIELD_GET(PIN_IO_SCHMITT, value);
- ret = cv1800_pinctrl_reg2schmitt(pctrl, pin, arg);
+ ret = sophgo_pinctrl_reg2schmitt(pctrl, sp, priv->power_cfg, arg);
if (ret < 0)
return ret;
arg = ret;
@@ -570,14 +307,16 @@ static int cv1800_pconf_get(struct pinctrl_dev *pctldev,
return enabled ? 0 : -EINVAL;
}
-static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl,
- struct cv1800_pin *pin,
+static int cv1800_pinconf_compute_config(struct sophgo_pinctrl *pctrl,
+ const struct sophgo_pin *sp,
unsigned long *configs,
unsigned int num_configs,
- u32 *value)
+ u32 *value, u32 *mask)
{
+ struct cv1800_priv *priv = pctrl->priv_ctrl;
+ const struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
int i;
- u32 v = 0;
+ u32 v = 0, m = 0;
enum cv1800_pin_io_type type;
int ret;
@@ -596,24 +335,30 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl,
case PIN_CONFIG_BIAS_PULL_DOWN:
v &= ~PIN_IO_PULLDOWN;
v |= FIELD_PREP(PIN_IO_PULLDOWN, arg);
+ m |= PIN_IO_PULLDOWN;
break;
case PIN_CONFIG_BIAS_PULL_UP:
v &= ~PIN_IO_PULLUP;
v |= FIELD_PREP(PIN_IO_PULLUP, arg);
+ m |= PIN_IO_PULLUP;
break;
case PIN_CONFIG_DRIVE_STRENGTH_UA:
- ret = cv1800_pinctrl_oc2reg(pctrl, pin, arg);
+ ret = sophgo_pinctrl_oc2reg(pctrl, sp,
+ priv->power_cfg, arg);
if (ret < 0)
return ret;
v &= ~PIN_IO_DRIVE;
v |= FIELD_PREP(PIN_IO_DRIVE, ret);
+ m |= PIN_IO_DRIVE;
break;
case PIN_CONFIG_INPUT_SCHMITT_UV:
- ret = cv1800_pinctrl_schmitt2reg(pctrl, pin, arg);
+ ret = sophgo_pinctrl_schmitt2reg(pctrl, sp,
+ priv->power_cfg, arg);
if (ret < 0)
return ret;
v &= ~PIN_IO_SCHMITT;
v |= FIELD_PREP(PIN_IO_SCHMITT, ret);
+ m |= PIN_IO_SCHMITT;
break;
case PIN_CONFIG_POWER_SOURCE:
/* Ignore power source as it is always fixed */
@@ -621,10 +366,12 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl,
case PIN_CONFIG_SLEW_RATE:
v &= ~PIN_IO_OUT_FAST_SLEW;
v |= FIELD_PREP(PIN_IO_OUT_FAST_SLEW, arg);
+ m |= PIN_IO_OUT_FAST_SLEW;
break;
case PIN_CONFIG_BIAS_BUS_HOLD:
v &= ~PIN_IO_BUS_HOLD;
v |= FIELD_PREP(PIN_IO_BUS_HOLD, arg);
+ m |= PIN_IO_BUS_HOLD;
break;
default:
return -ENOTSUPP;
@@ -632,134 +379,73 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl,
}
*value = v;
+ *mask = m;
return 0;
}
-static int cv1800_pin_set_config(struct cv1800_pinctrl *pctrl,
- unsigned int pin_id,
- u32 value)
+static int cv1800_set_pinconf_config(struct sophgo_pinctrl *pctrl,
+ const struct sophgo_pin *sp,
+ u32 value, u32 mask)
{
- struct cv1800_pin *pin = cv1800_get_pin(pctrl, pin_id);
- unsigned long flags;
+ struct cv1800_priv *priv = pctrl->priv_ctrl;
+ struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
void __iomem *addr;
+ u32 reg;
- if (!pin)
- return -EINVAL;
-
- addr = cv1800_pinctrl_get_component_addr(pctrl, &pin->conf);
+ addr = cv1800_pinctrl_get_component_addr(priv, &pin->conf);
- raw_spin_lock_irqsave(&pctrl->lock, flags);
- writel(value, addr);
- raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+ reg = readl(addr);
+ reg &= ~mask;
+ reg |= value;
+ writel(reg, addr);
return 0;
}
-static int cv1800_pconf_set(struct pinctrl_dev *pctldev,
- unsigned int pin_id, unsigned long *configs,
- unsigned int num_configs)
-{
- struct cv1800_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
- struct cv1800_pin *pin = cv1800_get_pin(pctrl, pin_id);
- u32 value;
-
- if (!pin)
- return -ENODEV;
-
- if (cv1800_pinconf_compute_config(pctrl, pin,
- configs, num_configs, &value))
- return -ENOTSUPP;
-
- return cv1800_pin_set_config(pctrl, pin_id, value);
-}
-
-static int cv1800_pconf_group_set(struct pinctrl_dev *pctldev,
- unsigned int gsel,
- unsigned long *configs,
- unsigned int num_configs)
-{
- struct cv1800_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
- const struct group_desc *group;
- const struct cv1800_pin_mux_config *pinmuxs;
- u32 value;
- int i;
-
- group = pinctrl_generic_get_group(pctldev, gsel);
- if (!group)
- return -EINVAL;
-
- pinmuxs = group->data;
-
- if (cv1800_pinconf_compute_config(pctrl, pinmuxs[0].pin,
- configs, num_configs, &value))
- return -ENOTSUPP;
-
- for (i = 0; i < group->grp.npins; i++)
- cv1800_pin_set_config(pctrl, group->grp.pins[i], value);
-
- return 0;
-}
-
-static const struct pinconf_ops cv1800_pconf_ops = {
+const struct pinconf_ops cv1800_pconf_ops = {
.pin_config_get = cv1800_pconf_get,
- .pin_config_set = cv1800_pconf_set,
- .pin_config_group_set = cv1800_pconf_group_set,
+ .pin_config_set = sophgo_pconf_set,
+ .pin_config_group_set = sophgo_pconf_group_set,
.is_generic = true,
};
+EXPORT_SYMBOL_GPL(cv1800_pconf_ops);
-int cv1800_pinctrl_probe(struct platform_device *pdev)
+static int cv1800_pinctrl_init(struct platform_device *pdev,
+ struct sophgo_pinctrl *pctrl)
{
- struct device *dev = &pdev->dev;
- struct cv1800_pinctrl *pctrl;
- const struct cv1800_pinctrl_data *pctrl_data;
- int ret;
-
- pctrl_data = device_get_match_data(dev);
- if (!pctrl_data)
- return -ENODEV;
+ const struct sophgo_pinctrl_data *pctrl_data = pctrl->data;
+ struct cv1800_priv *priv;
- if (pctrl_data->npins == 0 || pctrl_data->npd == 0)
- return dev_err_probe(dev, -EINVAL, "invalid pin data\n");
-
- pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL);
- if (!pctrl)
+ priv = devm_kzalloc(&pdev->dev, sizeof(struct cv1800_priv), GFP_KERNEL);
+ if (!priv)
return -ENOMEM;
- pctrl->power_cfg = devm_kcalloc(dev, pctrl_data->npd,
- sizeof(u32), GFP_KERNEL);
- if (!pctrl->power_cfg)
+ priv->power_cfg = devm_kcalloc(&pdev->dev, pctrl_data->npds,
+ sizeof(u32), GFP_KERNEL);
+ if (!priv->power_cfg)
return -ENOMEM;
- pctrl->regs[0] = devm_platform_ioremap_resource_byname(pdev, "sys");
- if (IS_ERR(pctrl->regs[0]))
- return PTR_ERR(pctrl->regs[0]);
-
- pctrl->regs[1] = devm_platform_ioremap_resource_byname(pdev, "rtc");
- if (IS_ERR(pctrl->regs[1]))
- return PTR_ERR(pctrl->regs[1]);
-
- pctrl->pdesc.name = dev_name(dev);
- pctrl->pdesc.pins = pctrl_data->pins;
- pctrl->pdesc.npins = pctrl_data->npins;
- pctrl->pdesc.pctlops = &cv1800_pctrl_ops;
- pctrl->pdesc.pmxops = &cv1800_pmx_ops;
- pctrl->pdesc.confops = &cv1800_pconf_ops;
- pctrl->pdesc.owner = THIS_MODULE;
-
- pctrl->data = pctrl_data;
- pctrl->dev = dev;
- raw_spin_lock_init(&pctrl->lock);
- mutex_init(&pctrl->mutex);
+ priv->regs[0] = devm_platform_ioremap_resource_byname(pdev, "sys");
+ if (IS_ERR(priv->regs[0]))
+ return PTR_ERR(priv->regs[0]);
- platform_set_drvdata(pdev, pctrl);
+ priv->regs[1] = devm_platform_ioremap_resource_byname(pdev, "rtc");
+ if (IS_ERR(priv->regs[1]))
+ return PTR_ERR(priv->regs[1]);
- 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");
+ pctrl->priv_ctrl = priv;
- return pinctrl_enable(pctrl->pctl_dev);
+ return 0;
}
-EXPORT_SYMBOL_GPL(cv1800_pinctrl_probe);
+
+const struct sophgo_cfg_ops cv1800_cfg_ops = {
+ .pctrl_init = cv1800_pinctrl_init,
+ .verify_pinmux_config = cv1800_verify_pinmux_config,
+ .verify_pin_group = cv1800_verify_pin_group,
+ .dt_node_to_map_post = cv1800_dt_node_to_map_post,
+ .compute_pinconf_config = cv1800_pinconf_compute_config,
+ .set_pinconf_config = cv1800_set_pinconf_config,
+ .set_pinmux_config = cv1800_set_pinmux_config,
+};
+EXPORT_SYMBOL_GPL(cv1800_cfg_ops);