0001
0002
0003
0004
0005 #include <linux/err.h>
0006 #include <linux/init.h>
0007 #include <linux/io.h>
0008 #include <linux/of.h>
0009 #include <linux/of_address.h>
0010 #include <linux/pinctrl/machine.h>
0011 #include <linux/pinctrl/pinconf.h>
0012 #include <linux/pinctrl/pinctrl.h>
0013 #include <linux/pinctrl/pinmux.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/slab.h>
0016 #include "../core.h"
0017 #include "pinctrl-mxs.h"
0018
0019 #define SUFFIX_LEN 4
0020
0021 struct mxs_pinctrl_data {
0022 struct device *dev;
0023 struct pinctrl_dev *pctl;
0024 void __iomem *base;
0025 struct mxs_pinctrl_soc_data *soc;
0026 };
0027
0028 static int mxs_get_groups_count(struct pinctrl_dev *pctldev)
0029 {
0030 struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
0031
0032 return d->soc->ngroups;
0033 }
0034
0035 static const char *mxs_get_group_name(struct pinctrl_dev *pctldev,
0036 unsigned group)
0037 {
0038 struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
0039
0040 return d->soc->groups[group].name;
0041 }
0042
0043 static int mxs_get_group_pins(struct pinctrl_dev *pctldev, unsigned group,
0044 const unsigned **pins, unsigned *num_pins)
0045 {
0046 struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
0047
0048 *pins = d->soc->groups[group].pins;
0049 *num_pins = d->soc->groups[group].npins;
0050
0051 return 0;
0052 }
0053
0054 static void mxs_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
0055 unsigned offset)
0056 {
0057 seq_printf(s, " %s", dev_name(pctldev->dev));
0058 }
0059
0060 static int mxs_dt_node_to_map(struct pinctrl_dev *pctldev,
0061 struct device_node *np,
0062 struct pinctrl_map **map, unsigned *num_maps)
0063 {
0064 struct pinctrl_map *new_map;
0065 char *group = NULL;
0066 unsigned new_num = 1;
0067 unsigned long config = 0;
0068 unsigned long *pconfig;
0069 int length = strlen(np->name) + SUFFIX_LEN;
0070 bool purecfg = false;
0071 u32 val, reg;
0072 int ret, i = 0;
0073
0074
0075 if (of_property_read_u32(np, "reg", ®))
0076 purecfg = true;
0077
0078 ret = of_property_read_u32(np, "fsl,drive-strength", &val);
0079 if (!ret)
0080 config = val | MA_PRESENT;
0081 ret = of_property_read_u32(np, "fsl,voltage", &val);
0082 if (!ret)
0083 config |= val << VOL_SHIFT | VOL_PRESENT;
0084 ret = of_property_read_u32(np, "fsl,pull-up", &val);
0085 if (!ret)
0086 config |= val << PULL_SHIFT | PULL_PRESENT;
0087
0088
0089 if (!purecfg && config)
0090 new_num = 2;
0091
0092 new_map = kcalloc(new_num, sizeof(*new_map), GFP_KERNEL);
0093 if (!new_map)
0094 return -ENOMEM;
0095
0096 if (!purecfg) {
0097 new_map[i].type = PIN_MAP_TYPE_MUX_GROUP;
0098 new_map[i].data.mux.function = np->name;
0099
0100
0101 group = kzalloc(length, GFP_KERNEL);
0102 if (!group) {
0103 ret = -ENOMEM;
0104 goto free;
0105 }
0106 snprintf(group, length, "%s.%d", np->name, reg);
0107 new_map[i].data.mux.group = group;
0108 i++;
0109 }
0110
0111 if (config) {
0112 pconfig = kmemdup(&config, sizeof(config), GFP_KERNEL);
0113 if (!pconfig) {
0114 ret = -ENOMEM;
0115 goto free_group;
0116 }
0117
0118 new_map[i].type = PIN_MAP_TYPE_CONFIGS_GROUP;
0119 new_map[i].data.configs.group_or_pin = purecfg ? np->name :
0120 group;
0121 new_map[i].data.configs.configs = pconfig;
0122 new_map[i].data.configs.num_configs = 1;
0123 }
0124
0125 *map = new_map;
0126 *num_maps = new_num;
0127
0128 return 0;
0129
0130 free_group:
0131 if (!purecfg)
0132 kfree(group);
0133 free:
0134 kfree(new_map);
0135 return ret;
0136 }
0137
0138 static void mxs_dt_free_map(struct pinctrl_dev *pctldev,
0139 struct pinctrl_map *map, unsigned num_maps)
0140 {
0141 u32 i;
0142
0143 for (i = 0; i < num_maps; i++) {
0144 if (map[i].type == PIN_MAP_TYPE_MUX_GROUP)
0145 kfree(map[i].data.mux.group);
0146 if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP)
0147 kfree(map[i].data.configs.configs);
0148 }
0149
0150 kfree(map);
0151 }
0152
0153 static const struct pinctrl_ops mxs_pinctrl_ops = {
0154 .get_groups_count = mxs_get_groups_count,
0155 .get_group_name = mxs_get_group_name,
0156 .get_group_pins = mxs_get_group_pins,
0157 .pin_dbg_show = mxs_pin_dbg_show,
0158 .dt_node_to_map = mxs_dt_node_to_map,
0159 .dt_free_map = mxs_dt_free_map,
0160 };
0161
0162 static int mxs_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev)
0163 {
0164 struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
0165
0166 return d->soc->nfunctions;
0167 }
0168
0169 static const char *mxs_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
0170 unsigned function)
0171 {
0172 struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
0173
0174 return d->soc->functions[function].name;
0175 }
0176
0177 static int mxs_pinctrl_get_func_groups(struct pinctrl_dev *pctldev,
0178 unsigned group,
0179 const char * const **groups,
0180 unsigned * const num_groups)
0181 {
0182 struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
0183
0184 *groups = d->soc->functions[group].groups;
0185 *num_groups = d->soc->functions[group].ngroups;
0186
0187 return 0;
0188 }
0189
0190 static void mxs_pinctrl_rmwl(u32 value, u32 mask, u8 shift, void __iomem *reg)
0191 {
0192 u32 tmp;
0193
0194 tmp = readl(reg);
0195 tmp &= ~(mask << shift);
0196 tmp |= value << shift;
0197 writel(tmp, reg);
0198 }
0199
0200 static int mxs_pinctrl_set_mux(struct pinctrl_dev *pctldev, unsigned selector,
0201 unsigned group)
0202 {
0203 struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
0204 struct mxs_group *g = &d->soc->groups[group];
0205 void __iomem *reg;
0206 u8 bank, shift;
0207 u16 pin;
0208 u32 i;
0209
0210 for (i = 0; i < g->npins; i++) {
0211 bank = PINID_TO_BANK(g->pins[i]);
0212 pin = PINID_TO_PIN(g->pins[i]);
0213 reg = d->base + d->soc->regs->muxsel;
0214 reg += bank * 0x20 + pin / 16 * 0x10;
0215 shift = pin % 16 * 2;
0216
0217 mxs_pinctrl_rmwl(g->muxsel[i], 0x3, shift, reg);
0218 }
0219
0220 return 0;
0221 }
0222
0223 static const struct pinmux_ops mxs_pinmux_ops = {
0224 .get_functions_count = mxs_pinctrl_get_funcs_count,
0225 .get_function_name = mxs_pinctrl_get_func_name,
0226 .get_function_groups = mxs_pinctrl_get_func_groups,
0227 .set_mux = mxs_pinctrl_set_mux,
0228 };
0229
0230 static int mxs_pinconf_get(struct pinctrl_dev *pctldev,
0231 unsigned pin, unsigned long *config)
0232 {
0233 return -ENOTSUPP;
0234 }
0235
0236 static int mxs_pinconf_set(struct pinctrl_dev *pctldev,
0237 unsigned pin, unsigned long *configs,
0238 unsigned num_configs)
0239 {
0240 return -ENOTSUPP;
0241 }
0242
0243 static int mxs_pinconf_group_get(struct pinctrl_dev *pctldev,
0244 unsigned group, unsigned long *config)
0245 {
0246 struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
0247
0248 *config = d->soc->groups[group].config;
0249
0250 return 0;
0251 }
0252
0253 static int mxs_pinconf_group_set(struct pinctrl_dev *pctldev,
0254 unsigned group, unsigned long *configs,
0255 unsigned num_configs)
0256 {
0257 struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
0258 struct mxs_group *g = &d->soc->groups[group];
0259 void __iomem *reg;
0260 u8 ma, vol, pull, bank, shift;
0261 u16 pin;
0262 u32 i;
0263 int n;
0264 unsigned long config;
0265
0266 for (n = 0; n < num_configs; n++) {
0267 config = configs[n];
0268
0269 ma = CONFIG_TO_MA(config);
0270 vol = CONFIG_TO_VOL(config);
0271 pull = CONFIG_TO_PULL(config);
0272
0273 for (i = 0; i < g->npins; i++) {
0274 bank = PINID_TO_BANK(g->pins[i]);
0275 pin = PINID_TO_PIN(g->pins[i]);
0276
0277
0278 reg = d->base + d->soc->regs->drive;
0279 reg += bank * 0x40 + pin / 8 * 0x10;
0280
0281
0282 if (config & MA_PRESENT) {
0283 shift = pin % 8 * 4;
0284 mxs_pinctrl_rmwl(ma, 0x3, shift, reg);
0285 }
0286
0287
0288 if (config & VOL_PRESENT) {
0289 shift = pin % 8 * 4 + 2;
0290 if (vol)
0291 writel(1 << shift, reg + SET);
0292 else
0293 writel(1 << shift, reg + CLR);
0294 }
0295
0296
0297 if (config & PULL_PRESENT) {
0298 reg = d->base + d->soc->regs->pull;
0299 reg += bank * 0x10;
0300 shift = pin;
0301 if (pull)
0302 writel(1 << shift, reg + SET);
0303 else
0304 writel(1 << shift, reg + CLR);
0305 }
0306 }
0307
0308
0309 g->config = config;
0310
0311 }
0312
0313 return 0;
0314 }
0315
0316 static void mxs_pinconf_dbg_show(struct pinctrl_dev *pctldev,
0317 struct seq_file *s, unsigned pin)
0318 {
0319
0320 }
0321
0322 static void mxs_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
0323 struct seq_file *s, unsigned group)
0324 {
0325 unsigned long config;
0326
0327 if (!mxs_pinconf_group_get(pctldev, group, &config))
0328 seq_printf(s, "0x%lx", config);
0329 }
0330
0331 static const struct pinconf_ops mxs_pinconf_ops = {
0332 .pin_config_get = mxs_pinconf_get,
0333 .pin_config_set = mxs_pinconf_set,
0334 .pin_config_group_get = mxs_pinconf_group_get,
0335 .pin_config_group_set = mxs_pinconf_group_set,
0336 .pin_config_dbg_show = mxs_pinconf_dbg_show,
0337 .pin_config_group_dbg_show = mxs_pinconf_group_dbg_show,
0338 };
0339
0340 static struct pinctrl_desc mxs_pinctrl_desc = {
0341 .pctlops = &mxs_pinctrl_ops,
0342 .pmxops = &mxs_pinmux_ops,
0343 .confops = &mxs_pinconf_ops,
0344 .owner = THIS_MODULE,
0345 };
0346
0347 static int mxs_pinctrl_parse_group(struct platform_device *pdev,
0348 struct device_node *np, int idx,
0349 const char **out_name)
0350 {
0351 struct mxs_pinctrl_data *d = platform_get_drvdata(pdev);
0352 struct mxs_group *g = &d->soc->groups[idx];
0353 struct property *prop;
0354 const char *propname = "fsl,pinmux-ids";
0355 char *group;
0356 int length = strlen(np->name) + SUFFIX_LEN;
0357 u32 val, i;
0358
0359 group = devm_kzalloc(&pdev->dev, length, GFP_KERNEL);
0360 if (!group)
0361 return -ENOMEM;
0362 if (of_property_read_u32(np, "reg", &val))
0363 snprintf(group, length, "%s", np->name);
0364 else
0365 snprintf(group, length, "%s.%d", np->name, val);
0366 g->name = group;
0367
0368 prop = of_find_property(np, propname, &length);
0369 if (!prop)
0370 return -EINVAL;
0371 g->npins = length / sizeof(u32);
0372
0373 g->pins = devm_kcalloc(&pdev->dev, g->npins, sizeof(*g->pins),
0374 GFP_KERNEL);
0375 if (!g->pins)
0376 return -ENOMEM;
0377
0378 g->muxsel = devm_kcalloc(&pdev->dev, g->npins, sizeof(*g->muxsel),
0379 GFP_KERNEL);
0380 if (!g->muxsel)
0381 return -ENOMEM;
0382
0383 of_property_read_u32_array(np, propname, g->pins, g->npins);
0384 for (i = 0; i < g->npins; i++) {
0385 g->muxsel[i] = MUXID_TO_MUXSEL(g->pins[i]);
0386 g->pins[i] = MUXID_TO_PINID(g->pins[i]);
0387 }
0388
0389 if (out_name)
0390 *out_name = g->name;
0391
0392 return 0;
0393 }
0394
0395 static int mxs_pinctrl_probe_dt(struct platform_device *pdev,
0396 struct mxs_pinctrl_data *d)
0397 {
0398 struct mxs_pinctrl_soc_data *soc = d->soc;
0399 struct device_node *np = pdev->dev.of_node;
0400 struct device_node *child;
0401 struct mxs_function *f;
0402 const char *gpio_compat = "fsl,mxs-gpio";
0403 const char *fn, *fnull = "";
0404 int i = 0, idxf = 0, idxg = 0;
0405 int ret;
0406 u32 val;
0407
0408 child = of_get_next_child(np, NULL);
0409 if (!child) {
0410 dev_err(&pdev->dev, "no group is defined\n");
0411 return -ENOENT;
0412 }
0413
0414
0415 fn = fnull;
0416 for_each_child_of_node(np, child) {
0417 if (of_device_is_compatible(child, gpio_compat))
0418 continue;
0419 soc->ngroups++;
0420
0421 if (of_property_read_u32(child, "reg", &val))
0422 continue;
0423 if (strcmp(fn, child->name)) {
0424 fn = child->name;
0425 soc->nfunctions++;
0426 }
0427 }
0428
0429 soc->functions = devm_kcalloc(&pdev->dev,
0430 soc->nfunctions,
0431 sizeof(*soc->functions),
0432 GFP_KERNEL);
0433 if (!soc->functions)
0434 return -ENOMEM;
0435
0436 soc->groups = devm_kcalloc(&pdev->dev,
0437 soc->ngroups, sizeof(*soc->groups),
0438 GFP_KERNEL);
0439 if (!soc->groups)
0440 return -ENOMEM;
0441
0442
0443 fn = fnull;
0444 f = &soc->functions[idxf];
0445 for_each_child_of_node(np, child) {
0446 if (of_device_is_compatible(child, gpio_compat))
0447 continue;
0448 if (of_property_read_u32(child, "reg", &val))
0449 continue;
0450 if (strcmp(fn, child->name)) {
0451 struct device_node *child2;
0452
0453
0454
0455
0456
0457 of_node_get(child);
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467 for (child2 = of_get_next_child(np, child);
0468 child2 != NULL;
0469 child2 = of_get_next_child(np, child2)) {
0470 if (!strcmp(child2->name, fn))
0471 dev_warn(&pdev->dev,
0472 "function nodes must be grouped by name (failed for: %s)",
0473 fn);
0474 }
0475
0476 f = &soc->functions[idxf++];
0477 f->name = fn = child->name;
0478 }
0479 f->ngroups++;
0480 }
0481
0482
0483 idxf = 0;
0484 fn = fnull;
0485 for_each_child_of_node(np, child) {
0486 if (of_device_is_compatible(child, gpio_compat))
0487 continue;
0488 if (of_property_read_u32(child, "reg", &val)) {
0489 ret = mxs_pinctrl_parse_group(pdev, child,
0490 idxg++, NULL);
0491 if (ret) {
0492 of_node_put(child);
0493 return ret;
0494 }
0495 continue;
0496 }
0497
0498 if (strcmp(fn, child->name)) {
0499 f = &soc->functions[idxf++];
0500 f->groups = devm_kcalloc(&pdev->dev,
0501 f->ngroups,
0502 sizeof(*f->groups),
0503 GFP_KERNEL);
0504 if (!f->groups) {
0505 of_node_put(child);
0506 return -ENOMEM;
0507 }
0508 fn = child->name;
0509 i = 0;
0510 }
0511 ret = mxs_pinctrl_parse_group(pdev, child, idxg++,
0512 &f->groups[i++]);
0513 if (ret) {
0514 of_node_put(child);
0515 return ret;
0516 }
0517 }
0518
0519 return 0;
0520 }
0521
0522 int mxs_pinctrl_probe(struct platform_device *pdev,
0523 struct mxs_pinctrl_soc_data *soc)
0524 {
0525 struct device_node *np = pdev->dev.of_node;
0526 struct mxs_pinctrl_data *d;
0527 int ret;
0528
0529 d = devm_kzalloc(&pdev->dev, sizeof(*d), GFP_KERNEL);
0530 if (!d)
0531 return -ENOMEM;
0532
0533 d->dev = &pdev->dev;
0534 d->soc = soc;
0535
0536 d->base = of_iomap(np, 0);
0537 if (!d->base)
0538 return -EADDRNOTAVAIL;
0539
0540 mxs_pinctrl_desc.pins = d->soc->pins;
0541 mxs_pinctrl_desc.npins = d->soc->npins;
0542 mxs_pinctrl_desc.name = dev_name(&pdev->dev);
0543
0544 platform_set_drvdata(pdev, d);
0545
0546 ret = mxs_pinctrl_probe_dt(pdev, d);
0547 if (ret) {
0548 dev_err(&pdev->dev, "dt probe failed: %d\n", ret);
0549 goto err;
0550 }
0551
0552 d->pctl = pinctrl_register(&mxs_pinctrl_desc, &pdev->dev, d);
0553 if (IS_ERR(d->pctl)) {
0554 dev_err(&pdev->dev, "Couldn't register MXS pinctrl driver\n");
0555 ret = PTR_ERR(d->pctl);
0556 goto err;
0557 }
0558
0559 return 0;
0560
0561 err:
0562 iounmap(d->base);
0563 return ret;
0564 }