Commit 5f266c60bf036a4adad2b69c1597ff49104959da

Authored by Purna Chandra Mandal
Committed by Daniel Schwierzeck
1 parent a0e7908326

drivers: pinctrl: Add pinctrl driver for Microchip PIC32.

In PIC32 pin-controller is a combined gpio-controller, pin-mux and
pin-config module. Remappable peripherals are assigned pins through
per-pin based muxing logic. And pin configuration are performed on
specific port registers which are shared along with gpio controller.
Note, non-remappable peripherals have default pins assigned thus
require no muxing.

Signed-off-by: Purna Chandra Mandal <purna.mandal@microchip.com>
Reviewed-by: Tom Rini <trini@konsulko.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

Showing 3 changed files with 374 additions and 0 deletions Side-by-side Diff

drivers/pinctrl/Kconfig
... ... @@ -131,6 +131,16 @@
131 131 actually does nothing but print debug messages when pinctrl
132 132 operations are invoked.
133 133  
  134 +config PIC32_PINCTRL
  135 + bool "Microchip PIC32 pin-control and pin-mux driver"
  136 + depends on DM && MACH_PIC32
  137 + default y
  138 + help
  139 + Supports individual pin selection and configuration for each remappable
  140 + peripheral available on Microchip PIC32 SoCs. This driver is controlled
  141 + by a device tree node which contains both GPIO defintion and pin control
  142 + functions.
  143 +
134 144 endif
135 145  
136 146 source "drivers/pinctrl/uniphier/Kconfig"
drivers/pinctrl/Makefile
... ... @@ -9,4 +9,5 @@
9 9 obj-$(CONFIG_PINCTRL_SANDBOX) += pinctrl-sandbox.o
10 10  
11 11 obj-$(CONFIG_ARCH_UNIPHIER) += uniphier/
  12 +obj-$(CONFIG_PIC32_PINCTRL) += pinctrl_pic32.o
drivers/pinctrl/pinctrl_pic32.c
  1 +/*
  2 + * Pinctrl driver for Microchip PIC32 SoCs
  3 + * Copyright (c) 2015 Microchip Technology Inc.
  4 + * Written by Purna Chandra Mandal <purna.mandal@microchip.com>
  5 + *
  6 + * SPDX-License-Identifier: GPL-2.0+
  7 + */
  8 +#include <common.h>
  9 +#include <dm.h>
  10 +#include <errno.h>
  11 +#include <asm/io.h>
  12 +#include <dm/pinctrl.h>
  13 +#include <dm/root.h>
  14 +#include <mach/pic32.h>
  15 +
  16 +DECLARE_GLOBAL_DATA_PTR;
  17 +
  18 +/* PIC32 has 10 peripheral ports with 16 pins each.
  19 + * Ports are marked PORTA-PORTK or PORT0-PORT9.
  20 + */
  21 +enum {
  22 + PIC32_PORT_A = 0,
  23 + PIC32_PORT_B = 1,
  24 + PIC32_PORT_C = 2,
  25 + PIC32_PORT_D = 3,
  26 + PIC32_PORT_E = 4,
  27 + PIC32_PORT_F = 5,
  28 + PIC32_PORT_G = 6,
  29 + PIC32_PORT_H = 7,
  30 + PIC32_PORT_J = 8, /* no PORT_I */
  31 + PIC32_PORT_K = 9,
  32 + PIC32_PINS_PER_PORT = 16,
  33 +};
  34 +
  35 +#define PIN_CONFIG_PIC32_DIGITAL (PIN_CONFIG_END + 1)
  36 +#define PIN_CONFIG_PIC32_ANALOG (PIN_CONFIG_END + 2)
  37 +
  38 +/* pin configuration descriptor */
  39 +struct pic32_pin_config {
  40 + u16 port; /* port number */
  41 + u16 pin; /* pin number in the port */
  42 + u32 config; /* one of PIN_CONFIG_* */
  43 +};
  44 +#define PIN_CONFIG(_prt, _pin, _cfg) \
  45 + {.port = (_prt), .pin = (_pin), .config = (_cfg), }
  46 +
  47 +/* In PIC32 muxing is performed at pin-level through two
  48 + * different set of registers - one set for input functions,
  49 + * and other for output functions.
  50 + * Pin configuration is handled through port register.
  51 + */
  52 +/* Port control registers */
  53 +struct pic32_reg_port {
  54 + struct pic32_reg_atomic ansel;
  55 + struct pic32_reg_atomic tris;
  56 + struct pic32_reg_atomic port;
  57 + struct pic32_reg_atomic lat;
  58 + struct pic32_reg_atomic odc;
  59 + struct pic32_reg_atomic cnpu;
  60 + struct pic32_reg_atomic cnpd;
  61 + struct pic32_reg_atomic cncon;
  62 + struct pic32_reg_atomic unused[8];
  63 +};
  64 +
  65 +/* Input function mux registers */
  66 +struct pic32_reg_in_mux {
  67 + u32 unused0;
  68 + u32 int1[4];
  69 + u32 unused1;
  70 + u32 t2ck[8];
  71 + u32 ic1[9];
  72 + u32 unused2;
  73 + u32 ocfar;
  74 + u32 unused3;
  75 + u32 u1rx;
  76 + u32 u1cts;
  77 + u32 u2rx;
  78 + u32 u2cts;
  79 + u32 u3rx;
  80 + u32 u3cts;
  81 + u32 u4rx;
  82 + u32 u4cts;
  83 + u32 u5rx;
  84 + u32 u5cts;
  85 + u32 u6rx;
  86 + u32 u6cts;
  87 + u32 unused4;
  88 + u32 sdi1;
  89 + u32 ss1;
  90 + u32 unused5;
  91 + u32 sdi2;
  92 + u32 ss2;
  93 + u32 unused6;
  94 + u32 sdi3;
  95 + u32 ss3;
  96 + u32 unused7;
  97 + u32 sdi4;
  98 + u32 ss4;
  99 + u32 unused8;
  100 + u32 sdi5;
  101 + u32 ss5;
  102 + u32 unused9;
  103 + u32 sdi6;
  104 + u32 ss6;
  105 + u32 c1rx;
  106 + u32 c2rx;
  107 + u32 refclki1;
  108 + u32 refclki2;
  109 + u32 refclki3;
  110 + u32 refclki4;
  111 +};
  112 +
  113 +/* output mux register offset */
  114 +#define PPS_OUT(__port, __pin) \
  115 + (((__port) * PIC32_PINS_PER_PORT + (__pin)) << 2)
  116 +
  117 +
  118 +struct pic32_pinctrl_priv {
  119 + struct pic32_reg_in_mux *mux_in; /* mux input function */
  120 + struct pic32_reg_port *pinconf; /* pin configuration*/
  121 + void __iomem *mux_out; /* mux output function */
  122 +};
  123 +
  124 +enum {
  125 + PERIPH_ID_UART1,
  126 + PERIPH_ID_UART2,
  127 + PERIPH_ID_ETH,
  128 + PERIPH_ID_USB,
  129 + PERIPH_ID_SDHCI,
  130 + PERIPH_ID_I2C1,
  131 + PERIPH_ID_I2C2,
  132 + PERIPH_ID_SPI1,
  133 + PERIPH_ID_SPI2,
  134 + PERIPH_ID_SQI,
  135 +};
  136 +
  137 +static int pic32_pinconfig_one(struct pic32_pinctrl_priv *priv,
  138 + u32 port_nr, u32 pin, u32 param)
  139 +{
  140 + struct pic32_reg_port *port;
  141 +
  142 + port = &priv->pinconf[port_nr];
  143 + switch (param) {
  144 + case PIN_CONFIG_PIC32_DIGITAL:
  145 + writel(BIT(pin), &port->ansel.clr);
  146 + break;
  147 + case PIN_CONFIG_PIC32_ANALOG:
  148 + writel(BIT(pin), &port->ansel.set);
  149 + break;
  150 + case PIN_CONFIG_INPUT_ENABLE:
  151 + writel(BIT(pin), &port->tris.set);
  152 + break;
  153 + case PIN_CONFIG_OUTPUT:
  154 + writel(BIT(pin), &port->tris.clr);
  155 + break;
  156 + case PIN_CONFIG_BIAS_PULL_UP:
  157 + writel(BIT(pin), &port->cnpu.set);
  158 + break;
  159 + case PIN_CONFIG_BIAS_PULL_DOWN:
  160 + writel(BIT(pin), &port->cnpd.set);
  161 + break;
  162 + case PIN_CONFIG_DRIVE_OPEN_DRAIN:
  163 + writel(BIT(pin), &port->odc.set);
  164 + break;
  165 + default:
  166 + break;
  167 + }
  168 +
  169 + return 0;
  170 +}
  171 +
  172 +static int pic32_pinconfig_set(struct pic32_pinctrl_priv *priv,
  173 + const struct pic32_pin_config *list, int count)
  174 +{
  175 + int i;
  176 +
  177 + for (i = 0 ; i < count; i++)
  178 + pic32_pinconfig_one(priv, list[i].port,
  179 + list[i].pin, list[i].config);
  180 +
  181 + return 0;
  182 +}
  183 +
  184 +static void pic32_eth_pin_config(struct udevice *dev)
  185 +{
  186 + struct pic32_pinctrl_priv *priv = dev_get_priv(dev);
  187 + const struct pic32_pin_config configs[] = {
  188 + /* EMDC - D11 */
  189 + PIN_CONFIG(PIC32_PORT_D, 11, PIN_CONFIG_PIC32_DIGITAL),
  190 + PIN_CONFIG(PIC32_PORT_D, 11, PIN_CONFIG_OUTPUT),
  191 + /* ETXEN */
  192 + PIN_CONFIG(PIC32_PORT_D, 6, PIN_CONFIG_PIC32_DIGITAL),
  193 + PIN_CONFIG(PIC32_PORT_D, 6, PIN_CONFIG_OUTPUT),
  194 + /* ECRSDV */
  195 + PIN_CONFIG(PIC32_PORT_H, 13, PIN_CONFIG_PIC32_DIGITAL),
  196 + PIN_CONFIG(PIC32_PORT_H, 13, PIN_CONFIG_INPUT_ENABLE),
  197 + /* ERXD0 */
  198 + PIN_CONFIG(PIC32_PORT_H, 8, PIN_CONFIG_PIC32_DIGITAL),
  199 + PIN_CONFIG(PIC32_PORT_H, 8, PIN_CONFIG_INPUT_ENABLE),
  200 + PIN_CONFIG(PIC32_PORT_H, 8, PIN_CONFIG_BIAS_PULL_DOWN),
  201 + /* ERXD1 */
  202 + PIN_CONFIG(PIC32_PORT_H, 5, PIN_CONFIG_PIC32_DIGITAL),
  203 + PIN_CONFIG(PIC32_PORT_H, 5, PIN_CONFIG_INPUT_ENABLE),
  204 + PIN_CONFIG(PIC32_PORT_H, 5, PIN_CONFIG_BIAS_PULL_DOWN),
  205 + /* EREFCLK */
  206 + PIN_CONFIG(PIC32_PORT_J, 11, PIN_CONFIG_PIC32_DIGITAL),
  207 + PIN_CONFIG(PIC32_PORT_J, 11, PIN_CONFIG_INPUT_ENABLE),
  208 + /* ETXD1 */
  209 + PIN_CONFIG(PIC32_PORT_J, 9, PIN_CONFIG_PIC32_DIGITAL),
  210 + PIN_CONFIG(PIC32_PORT_J, 9, PIN_CONFIG_OUTPUT),
  211 + /* ETXD0 */
  212 + PIN_CONFIG(PIC32_PORT_J, 8, PIN_CONFIG_PIC32_DIGITAL),
  213 + PIN_CONFIG(PIC32_PORT_J, 8, PIN_CONFIG_OUTPUT),
  214 + /* EMDIO */
  215 + PIN_CONFIG(PIC32_PORT_J, 1, PIN_CONFIG_PIC32_DIGITAL),
  216 + PIN_CONFIG(PIC32_PORT_J, 1, PIN_CONFIG_INPUT_ENABLE),
  217 + /* ERXERR */
  218 + PIN_CONFIG(PIC32_PORT_F, 3, PIN_CONFIG_PIC32_DIGITAL),
  219 + PIN_CONFIG(PIC32_PORT_F, 3, PIN_CONFIG_INPUT_ENABLE),
  220 + };
  221 +
  222 + pic32_pinconfig_set(priv, configs, ARRAY_SIZE(configs));
  223 +}
  224 +
  225 +static int pic32_pinctrl_request(struct udevice *dev, int func, int flags)
  226 +{
  227 + struct pic32_pinctrl_priv *priv = dev_get_priv(dev);
  228 +
  229 + switch (func) {
  230 + case PERIPH_ID_UART2:
  231 + /* PPS for U2 RX/TX */
  232 + writel(0x02, priv->mux_out + PPS_OUT(PIC32_PORT_G, 9));
  233 + writel(0x05, &priv->mux_in->u2rx); /* B0 */
  234 + /* set digital mode */
  235 + pic32_pinconfig_one(priv, PIC32_PORT_G, 9,
  236 + PIN_CONFIG_PIC32_DIGITAL);
  237 + pic32_pinconfig_one(priv, PIC32_PORT_B, 0,
  238 + PIN_CONFIG_PIC32_DIGITAL);
  239 + break;
  240 + case PERIPH_ID_ETH:
  241 + pic32_eth_pin_config(dev);
  242 + break;
  243 + default:
  244 + debug("%s: unknown-unhandled case\n", __func__);
  245 + break;
  246 + }
  247 +
  248 + return 0;
  249 +}
  250 +
  251 +static int pic32_pinctrl_get_periph_id(struct udevice *dev,
  252 + struct udevice *periph)
  253 +{
  254 + int ret;
  255 + u32 cell[2];
  256 +
  257 + ret = fdtdec_get_int_array(gd->fdt_blob, periph->of_offset,
  258 + "interrupts", cell, ARRAY_SIZE(cell));
  259 + if (ret < 0)
  260 + return -EINVAL;
  261 +
  262 + /* interrupt number */
  263 + switch (cell[0]) {
  264 + case 112 ... 114:
  265 + return PERIPH_ID_UART1;
  266 + case 145 ... 147:
  267 + return PERIPH_ID_UART2;
  268 + case 109 ... 111:
  269 + return PERIPH_ID_SPI1;
  270 + case 142 ... 144:
  271 + return PERIPH_ID_SPI2;
  272 + case 115 ... 117:
  273 + return PERIPH_ID_I2C1;
  274 + case 148 ... 150:
  275 + return PERIPH_ID_I2C2;
  276 + case 132 ... 133:
  277 + return PERIPH_ID_USB;
  278 + case 169:
  279 + return PERIPH_ID_SQI;
  280 + case 191:
  281 + return PERIPH_ID_SDHCI;
  282 + case 153:
  283 + return PERIPH_ID_ETH;
  284 + default:
  285 + break;
  286 + }
  287 +
  288 + return -ENOENT;
  289 +}
  290 +
  291 +static int pic32_pinctrl_set_state_simple(struct udevice *dev,
  292 + struct udevice *periph)
  293 +{
  294 + int func;
  295 +
  296 + debug("%s: periph %s\n", __func__, periph->name);
  297 + func = pic32_pinctrl_get_periph_id(dev, periph);
  298 + if (func < 0)
  299 + return func;
  300 + return pic32_pinctrl_request(dev, func, 0);
  301 +}
  302 +
  303 +static struct pinctrl_ops pic32_pinctrl_ops = {
  304 + .set_state_simple = pic32_pinctrl_set_state_simple,
  305 + .request = pic32_pinctrl_request,
  306 + .get_periph_id = pic32_pinctrl_get_periph_id,
  307 +};
  308 +
  309 +static int pic32_pinctrl_probe(struct udevice *dev)
  310 +{
  311 + struct pic32_pinctrl_priv *priv = dev_get_priv(dev);
  312 + struct fdt_resource res;
  313 + void *fdt = (void *)gd->fdt_blob;
  314 + int node = dev->of_offset;
  315 + int ret;
  316 +
  317 + ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
  318 + "ppsin", &res);
  319 + if (ret < 0) {
  320 + printf("pinctrl: resource \"ppsin\" not found\n");
  321 + return ret;
  322 + }
  323 + priv->mux_in = ioremap(res.start, fdt_resource_size(&res));
  324 +
  325 + ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
  326 + "ppsout", &res);
  327 + if (ret < 0) {
  328 + printf("pinctrl: resource \"ppsout\" not found\n");
  329 + return ret;
  330 + }
  331 + priv->mux_out = ioremap(res.start, fdt_resource_size(&res));
  332 +
  333 + ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
  334 + "port", &res);
  335 + if (ret < 0) {
  336 + printf("pinctrl: resource \"port\" not found\n");
  337 + return ret;
  338 + }
  339 + priv->pinconf = ioremap(res.start, fdt_resource_size(&res));
  340 +
  341 + return 0;
  342 +}
  343 +
  344 +static int pic32_pinctrl_bind(struct udevice *dev)
  345 +{
  346 + /* scan child GPIO banks */
  347 + return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
  348 +}
  349 +
  350 +static const struct udevice_id pic32_pinctrl_ids[] = {
  351 + { .compatible = "microchip,pic32mzda-pinctrl" },
  352 + { }
  353 +};
  354 +
  355 +U_BOOT_DRIVER(pinctrl_pic32) = {
  356 + .name = "pinctrl_pic32",
  357 + .id = UCLASS_PINCTRL,
  358 + .of_match = pic32_pinctrl_ids,
  359 + .ops = &pic32_pinctrl_ops,
  360 + .probe = pic32_pinctrl_probe,
  361 + .bind = pic32_pinctrl_bind,
  362 + .priv_auto_alloc_size = sizeof(struct pic32_pinctrl_priv),
  363 +};