diff options
| author | Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> | 2012-12-15 17:51:19 -0500 |
|---|---|---|
| committer | Simon Horman <horms+renesas@verge.net.au> | 2013-01-24 19:24:25 -0500 |
| commit | 6e54d8d252ed09ae148af6565971974af9a96e10 (patch) | |
| tree | ac4e0c344ec0e371decf95663d75f7918bd33bbc /drivers/sh/pfc | |
| parent | 56dc04af3b5e54be330e18630301d2bda5d365eb (diff) | |
sh-pfc: Move driver from drivers/sh/ to drivers/pinctrl/
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Acked-by: Paul Mundt <lethal@linux-sh.org>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
Diffstat (limited to 'drivers/sh/pfc')
| -rw-r--r-- | drivers/sh/pfc/Kconfig | 18 | ||||
| -rw-r--r-- | drivers/sh/pfc/Makefile | 5 | ||||
| -rw-r--r-- | drivers/sh/pfc/core.c | 586 | ||||
| -rw-r--r-- | drivers/sh/pfc/core.h | 54 | ||||
| -rw-r--r-- | drivers/sh/pfc/gpio.c | 179 | ||||
| -rw-r--r-- | drivers/sh/pfc/pinctrl.c | 464 |
6 files changed, 0 insertions, 1306 deletions
diff --git a/drivers/sh/pfc/Kconfig b/drivers/sh/pfc/Kconfig deleted file mode 100644 index eaeabc58bb06..000000000000 --- a/drivers/sh/pfc/Kconfig +++ /dev/null | |||
| @@ -1,18 +0,0 @@ | |||
| 1 | comment "Pin function controller options" | ||
| 2 | |||
| 3 | config SH_PFC | ||
| 4 | # XXX move off the gpio dependency | ||
| 5 | depends on GENERIC_GPIO | ||
| 6 | select GPIO_SH_PFC if ARCH_REQUIRE_GPIOLIB | ||
| 7 | select PINCTRL_SH_PFC | ||
| 8 | select PINCTRL | ||
| 9 | select PINMUX | ||
| 10 | select PINCONF | ||
| 11 | def_bool y | ||
| 12 | |||
| 13 | config GPIO_SH_PFC | ||
| 14 | bool "SuperH PFC GPIO support" | ||
| 15 | depends on SH_PFC && GPIOLIB | ||
| 16 | help | ||
| 17 | This enables support for GPIOs within the SoC's pin function | ||
| 18 | controller. | ||
diff --git a/drivers/sh/pfc/Makefile b/drivers/sh/pfc/Makefile deleted file mode 100644 index 6315cf35b34d..000000000000 --- a/drivers/sh/pfc/Makefile +++ /dev/null | |||
| @@ -1,5 +0,0 @@ | |||
| 1 | sh-pfc-objs = core.o pinctrl.o | ||
| 2 | ifeq ($(CONFIG_GPIO_SH_PFC),y) | ||
| 3 | sh-pfc-objs += gpio.o | ||
| 4 | endif | ||
| 5 | obj-y += sh-pfc.o | ||
diff --git a/drivers/sh/pfc/core.c b/drivers/sh/pfc/core.c deleted file mode 100644 index 8e7818bccb29..000000000000 --- a/drivers/sh/pfc/core.c +++ /dev/null | |||
| @@ -1,586 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * SuperH Pin Function Controller support. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Magnus Damm | ||
| 5 | * Copyright (C) 2009 - 2012 Paul Mundt | ||
| 6 | * | ||
| 7 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 8 | * License. See the file "COPYING" in the main directory of this archive | ||
| 9 | * for more details. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #define DRV_NAME "sh-pfc" | ||
| 13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 14 | |||
| 15 | #include <linux/bitops.h> | ||
| 16 | #include <linux/err.h> | ||
| 17 | #include <linux/errno.h> | ||
| 18 | #include <linux/io.h> | ||
| 19 | #include <linux/ioport.h> | ||
| 20 | #include <linux/kernel.h> | ||
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/pinctrl/machine.h> | ||
| 23 | #include <linux/platform_device.h> | ||
| 24 | #include <linux/sh_pfc.h> | ||
| 25 | #include <linux/slab.h> | ||
| 26 | |||
| 27 | #include "core.h" | ||
| 28 | |||
| 29 | static int sh_pfc_ioremap(struct sh_pfc *pfc, struct platform_device *pdev) | ||
| 30 | { | ||
| 31 | struct resource *res; | ||
| 32 | int k; | ||
| 33 | |||
| 34 | if (pdev->num_resources == 0) { | ||
| 35 | pfc->num_windows = 0; | ||
| 36 | return 0; | ||
| 37 | } | ||
| 38 | |||
| 39 | pfc->window = devm_kzalloc(pfc->dev, pdev->num_resources * | ||
| 40 | sizeof(*pfc->window), GFP_NOWAIT); | ||
| 41 | if (!pfc->window) | ||
| 42 | return -ENOMEM; | ||
| 43 | |||
| 44 | pfc->num_windows = pdev->num_resources; | ||
| 45 | |||
| 46 | for (k = 0, res = pdev->resource; k < pdev->num_resources; k++, res++) { | ||
| 47 | WARN_ON(resource_type(res) != IORESOURCE_MEM); | ||
| 48 | pfc->window[k].phys = res->start; | ||
| 49 | pfc->window[k].size = resource_size(res); | ||
| 50 | pfc->window[k].virt = devm_ioremap_nocache(pfc->dev, res->start, | ||
| 51 | resource_size(res)); | ||
| 52 | if (!pfc->window[k].virt) | ||
| 53 | return -ENOMEM; | ||
| 54 | } | ||
| 55 | |||
| 56 | return 0; | ||
| 57 | } | ||
| 58 | |||
| 59 | static void __iomem *sh_pfc_phys_to_virt(struct sh_pfc *pfc, | ||
| 60 | unsigned long address) | ||
| 61 | { | ||
| 62 | struct sh_pfc_window *window; | ||
| 63 | int k; | ||
| 64 | |||
| 65 | /* scan through physical windows and convert address */ | ||
| 66 | for (k = 0; k < pfc->num_windows; k++) { | ||
| 67 | window = pfc->window + k; | ||
| 68 | |||
| 69 | if (address < window->phys) | ||
| 70 | continue; | ||
| 71 | |||
| 72 | if (address >= (window->phys + window->size)) | ||
| 73 | continue; | ||
| 74 | |||
| 75 | return window->virt + (address - window->phys); | ||
| 76 | } | ||
| 77 | |||
| 78 | /* no windows defined, register must be 1:1 mapped virt:phys */ | ||
| 79 | return (void __iomem *)address; | ||
| 80 | } | ||
| 81 | |||
| 82 | static int sh_pfc_enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r) | ||
| 83 | { | ||
| 84 | if (enum_id < r->begin) | ||
| 85 | return 0; | ||
| 86 | |||
| 87 | if (enum_id > r->end) | ||
| 88 | return 0; | ||
| 89 | |||
| 90 | return 1; | ||
| 91 | } | ||
| 92 | |||
| 93 | static unsigned long sh_pfc_read_raw_reg(void __iomem *mapped_reg, | ||
| 94 | unsigned long reg_width) | ||
| 95 | { | ||
| 96 | switch (reg_width) { | ||
| 97 | case 8: | ||
| 98 | return ioread8(mapped_reg); | ||
| 99 | case 16: | ||
| 100 | return ioread16(mapped_reg); | ||
| 101 | case 32: | ||
| 102 | return ioread32(mapped_reg); | ||
| 103 | } | ||
| 104 | |||
| 105 | BUG(); | ||
| 106 | return 0; | ||
| 107 | } | ||
| 108 | |||
| 109 | static void sh_pfc_write_raw_reg(void __iomem *mapped_reg, | ||
| 110 | unsigned long reg_width, unsigned long data) | ||
| 111 | { | ||
| 112 | switch (reg_width) { | ||
| 113 | case 8: | ||
| 114 | iowrite8(data, mapped_reg); | ||
| 115 | return; | ||
| 116 | case 16: | ||
| 117 | iowrite16(data, mapped_reg); | ||
| 118 | return; | ||
| 119 | case 32: | ||
| 120 | iowrite32(data, mapped_reg); | ||
| 121 | return; | ||
| 122 | } | ||
| 123 | |||
| 124 | BUG(); | ||
| 125 | } | ||
| 126 | |||
| 127 | int sh_pfc_read_bit(struct pinmux_data_reg *dr, unsigned long in_pos) | ||
| 128 | { | ||
| 129 | unsigned long pos; | ||
| 130 | |||
| 131 | pos = dr->reg_width - (in_pos + 1); | ||
| 132 | |||
| 133 | pr_debug("read_bit: addr = %lx, pos = %ld, " | ||
| 134 | "r_width = %ld\n", dr->reg, pos, dr->reg_width); | ||
| 135 | |||
| 136 | return (sh_pfc_read_raw_reg(dr->mapped_reg, dr->reg_width) >> pos) & 1; | ||
| 137 | } | ||
| 138 | |||
| 139 | void sh_pfc_write_bit(struct pinmux_data_reg *dr, unsigned long in_pos, | ||
| 140 | unsigned long value) | ||
| 141 | { | ||
| 142 | unsigned long pos; | ||
| 143 | |||
| 144 | pos = dr->reg_width - (in_pos + 1); | ||
| 145 | |||
| 146 | pr_debug("write_bit addr = %lx, value = %d, pos = %ld, " | ||
| 147 | "r_width = %ld\n", | ||
| 148 | dr->reg, !!value, pos, dr->reg_width); | ||
| 149 | |||
| 150 | if (value) | ||
| 151 | set_bit(pos, &dr->reg_shadow); | ||
| 152 | else | ||
| 153 | clear_bit(pos, &dr->reg_shadow); | ||
| 154 | |||
| 155 | sh_pfc_write_raw_reg(dr->mapped_reg, dr->reg_width, dr->reg_shadow); | ||
| 156 | } | ||
| 157 | |||
| 158 | static void sh_pfc_config_reg_helper(struct sh_pfc *pfc, | ||
| 159 | struct pinmux_cfg_reg *crp, | ||
| 160 | unsigned long in_pos, | ||
| 161 | void __iomem **mapped_regp, | ||
| 162 | unsigned long *maskp, | ||
| 163 | unsigned long *posp) | ||
| 164 | { | ||
| 165 | int k; | ||
| 166 | |||
| 167 | *mapped_regp = sh_pfc_phys_to_virt(pfc, crp->reg); | ||
| 168 | |||
| 169 | if (crp->field_width) { | ||
| 170 | *maskp = (1 << crp->field_width) - 1; | ||
| 171 | *posp = crp->reg_width - ((in_pos + 1) * crp->field_width); | ||
| 172 | } else { | ||
| 173 | *maskp = (1 << crp->var_field_width[in_pos]) - 1; | ||
| 174 | *posp = crp->reg_width; | ||
| 175 | for (k = 0; k <= in_pos; k++) | ||
| 176 | *posp -= crp->var_field_width[k]; | ||
| 177 | } | ||
| 178 | } | ||
| 179 | |||
| 180 | static int sh_pfc_read_config_reg(struct sh_pfc *pfc, | ||
| 181 | struct pinmux_cfg_reg *crp, | ||
| 182 | unsigned long field) | ||
| 183 | { | ||
| 184 | void __iomem *mapped_reg; | ||
| 185 | unsigned long mask, pos; | ||
| 186 | |||
| 187 | sh_pfc_config_reg_helper(pfc, crp, field, &mapped_reg, &mask, &pos); | ||
| 188 | |||
| 189 | pr_debug("read_reg: addr = %lx, field = %ld, " | ||
| 190 | "r_width = %ld, f_width = %ld\n", | ||
| 191 | crp->reg, field, crp->reg_width, crp->field_width); | ||
| 192 | |||
| 193 | return (sh_pfc_read_raw_reg(mapped_reg, crp->reg_width) >> pos) & mask; | ||
| 194 | } | ||
| 195 | |||
| 196 | static void sh_pfc_write_config_reg(struct sh_pfc *pfc, | ||
| 197 | struct pinmux_cfg_reg *crp, | ||
| 198 | unsigned long field, unsigned long value) | ||
| 199 | { | ||
| 200 | void __iomem *mapped_reg; | ||
| 201 | unsigned long mask, pos, data; | ||
| 202 | |||
| 203 | sh_pfc_config_reg_helper(pfc, crp, field, &mapped_reg, &mask, &pos); | ||
| 204 | |||
| 205 | pr_debug("write_reg addr = %lx, value = %ld, field = %ld, " | ||
| 206 | "r_width = %ld, f_width = %ld\n", | ||
| 207 | crp->reg, value, field, crp->reg_width, crp->field_width); | ||
| 208 | |||
| 209 | mask = ~(mask << pos); | ||
| 210 | value = value << pos; | ||
| 211 | |||
| 212 | data = sh_pfc_read_raw_reg(mapped_reg, crp->reg_width); | ||
| 213 | data &= mask; | ||
| 214 | data |= value; | ||
| 215 | |||
| 216 | if (pfc->pdata->unlock_reg) | ||
| 217 | sh_pfc_write_raw_reg( | ||
| 218 | sh_pfc_phys_to_virt(pfc, pfc->pdata->unlock_reg), 32, | ||
| 219 | ~data); | ||
| 220 | |||
| 221 | sh_pfc_write_raw_reg(mapped_reg, crp->reg_width, data); | ||
| 222 | } | ||
| 223 | |||
| 224 | static int sh_pfc_setup_data_reg(struct sh_pfc *pfc, unsigned gpio) | ||
| 225 | { | ||
| 226 | struct pinmux_gpio *gpiop = &pfc->pdata->gpios[gpio]; | ||
| 227 | struct pinmux_data_reg *data_reg; | ||
| 228 | int k, n; | ||
| 229 | |||
| 230 | if (!sh_pfc_enum_in_range(gpiop->enum_id, &pfc->pdata->data)) | ||
| 231 | return -1; | ||
| 232 | |||
| 233 | k = 0; | ||
| 234 | while (1) { | ||
| 235 | data_reg = pfc->pdata->data_regs + k; | ||
| 236 | |||
| 237 | if (!data_reg->reg_width) | ||
| 238 | break; | ||
| 239 | |||
| 240 | data_reg->mapped_reg = sh_pfc_phys_to_virt(pfc, data_reg->reg); | ||
| 241 | |||
| 242 | for (n = 0; n < data_reg->reg_width; n++) { | ||
| 243 | if (data_reg->enum_ids[n] == gpiop->enum_id) { | ||
| 244 | gpiop->flags &= ~PINMUX_FLAG_DREG; | ||
| 245 | gpiop->flags |= (k << PINMUX_FLAG_DREG_SHIFT); | ||
| 246 | gpiop->flags &= ~PINMUX_FLAG_DBIT; | ||
| 247 | gpiop->flags |= (n << PINMUX_FLAG_DBIT_SHIFT); | ||
| 248 | return 0; | ||
| 249 | } | ||
| 250 | } | ||
| 251 | k++; | ||
| 252 | } | ||
| 253 | |||
| 254 | BUG(); | ||
| 255 | |||
| 256 | return -1; | ||
| 257 | } | ||
| 258 | |||
| 259 | static void sh_pfc_setup_data_regs(struct sh_pfc *pfc) | ||
| 260 | { | ||
| 261 | struct pinmux_data_reg *drp; | ||
| 262 | int k; | ||
| 263 | |||
| 264 | for (k = pfc->pdata->first_gpio; k <= pfc->pdata->last_gpio; k++) | ||
| 265 | sh_pfc_setup_data_reg(pfc, k); | ||
| 266 | |||
| 267 | k = 0; | ||
| 268 | while (1) { | ||
| 269 | drp = pfc->pdata->data_regs + k; | ||
| 270 | |||
| 271 | if (!drp->reg_width) | ||
| 272 | break; | ||
| 273 | |||
| 274 | drp->reg_shadow = sh_pfc_read_raw_reg(drp->mapped_reg, | ||
| 275 | drp->reg_width); | ||
| 276 | k++; | ||
| 277 | } | ||
| 278 | } | ||
| 279 | |||
| 280 | int sh_pfc_get_data_reg(struct sh_pfc *pfc, unsigned gpio, | ||
| 281 | struct pinmux_data_reg **drp, int *bitp) | ||
| 282 | { | ||
| 283 | struct pinmux_gpio *gpiop = &pfc->pdata->gpios[gpio]; | ||
| 284 | int k, n; | ||
| 285 | |||
| 286 | if (!sh_pfc_enum_in_range(gpiop->enum_id, &pfc->pdata->data)) | ||
| 287 | return -1; | ||
| 288 | |||
| 289 | k = (gpiop->flags & PINMUX_FLAG_DREG) >> PINMUX_FLAG_DREG_SHIFT; | ||
| 290 | n = (gpiop->flags & PINMUX_FLAG_DBIT) >> PINMUX_FLAG_DBIT_SHIFT; | ||
| 291 | *drp = pfc->pdata->data_regs + k; | ||
| 292 | *bitp = n; | ||
| 293 | return 0; | ||
| 294 | } | ||
| 295 | |||
| 296 | static int sh_pfc_get_config_reg(struct sh_pfc *pfc, pinmux_enum_t enum_id, | ||
| 297 | struct pinmux_cfg_reg **crp, int *fieldp, | ||
| 298 | int *valuep, unsigned long **cntp) | ||
| 299 | { | ||
| 300 | struct pinmux_cfg_reg *config_reg; | ||
| 301 | unsigned long r_width, f_width, curr_width, ncomb; | ||
| 302 | int k, m, n, pos, bit_pos; | ||
| 303 | |||
| 304 | k = 0; | ||
| 305 | while (1) { | ||
| 306 | config_reg = pfc->pdata->cfg_regs + k; | ||
| 307 | |||
| 308 | r_width = config_reg->reg_width; | ||
| 309 | f_width = config_reg->field_width; | ||
| 310 | |||
| 311 | if (!r_width) | ||
| 312 | break; | ||
| 313 | |||
| 314 | pos = 0; | ||
| 315 | m = 0; | ||
| 316 | for (bit_pos = 0; bit_pos < r_width; bit_pos += curr_width) { | ||
| 317 | if (f_width) | ||
| 318 | curr_width = f_width; | ||
| 319 | else | ||
| 320 | curr_width = config_reg->var_field_width[m]; | ||
| 321 | |||
| 322 | ncomb = 1 << curr_width; | ||
| 323 | for (n = 0; n < ncomb; n++) { | ||
| 324 | if (config_reg->enum_ids[pos + n] == enum_id) { | ||
| 325 | *crp = config_reg; | ||
| 326 | *fieldp = m; | ||
| 327 | *valuep = n; | ||
| 328 | *cntp = &config_reg->cnt[m]; | ||
| 329 | return 0; | ||
| 330 | } | ||
| 331 | } | ||
| 332 | pos += ncomb; | ||
| 333 | m++; | ||
| 334 | } | ||
| 335 | k++; | ||
| 336 | } | ||
| 337 | |||
| 338 | return -1; | ||
| 339 | } | ||
| 340 | |||
| 341 | int sh_pfc_gpio_to_enum(struct sh_pfc *pfc, unsigned gpio, int pos, | ||
| 342 | pinmux_enum_t *enum_idp) | ||
| 343 | { | ||
| 344 | pinmux_enum_t enum_id = pfc->pdata->gpios[gpio].enum_id; | ||
| 345 | pinmux_enum_t *data = pfc->pdata->gpio_data; | ||
| 346 | int k; | ||
| 347 | |||
| 348 | if (!sh_pfc_enum_in_range(enum_id, &pfc->pdata->data)) { | ||
| 349 | if (!sh_pfc_enum_in_range(enum_id, &pfc->pdata->mark)) { | ||
| 350 | pr_err("non data/mark enum_id for gpio %d\n", gpio); | ||
| 351 | return -1; | ||
| 352 | } | ||
| 353 | } | ||
| 354 | |||
| 355 | if (pos) { | ||
| 356 | *enum_idp = data[pos + 1]; | ||
| 357 | return pos + 1; | ||
| 358 | } | ||
| 359 | |||
| 360 | for (k = 0; k < pfc->pdata->gpio_data_size; k++) { | ||
| 361 | if (data[k] == enum_id) { | ||
| 362 | *enum_idp = data[k + 1]; | ||
| 363 | return k + 1; | ||
| 364 | } | ||
| 365 | } | ||
| 366 | |||
| 367 | pr_err("cannot locate data/mark enum_id for gpio %d\n", gpio); | ||
| 368 | return -1; | ||
| 369 | } | ||
| 370 | |||
| 371 | int sh_pfc_config_gpio(struct sh_pfc *pfc, unsigned gpio, int pinmux_type, | ||
| 372 | int cfg_mode) | ||
| 373 | { | ||
| 374 | struct pinmux_cfg_reg *cr = NULL; | ||
| 375 | pinmux_enum_t enum_id; | ||
| 376 | struct pinmux_range *range; | ||
| 377 | int in_range, pos, field, value; | ||
| 378 | unsigned long *cntp; | ||
| 379 | |||
| 380 | switch (pinmux_type) { | ||
| 381 | |||
| 382 | case PINMUX_TYPE_FUNCTION: | ||
| 383 | range = NULL; | ||
| 384 | break; | ||
| 385 | |||
| 386 | case PINMUX_TYPE_OUTPUT: | ||
| 387 | range = &pfc->pdata->output; | ||
| 388 | break; | ||
| 389 | |||
| 390 | case PINMUX_TYPE_INPUT: | ||
| 391 | range = &pfc->pdata->input; | ||
| 392 | break; | ||
| 393 | |||
| 394 | case PINMUX_TYPE_INPUT_PULLUP: | ||
| 395 | range = &pfc->pdata->input_pu; | ||
| 396 | break; | ||
| 397 | |||
| 398 | case PINMUX_TYPE_INPUT_PULLDOWN: | ||
| 399 | range = &pfc->pdata->input_pd; | ||
| 400 | break; | ||
| 401 | |||
| 402 | default: | ||
| 403 | goto out_err; | ||
| 404 | } | ||
| 405 | |||
| 406 | pos = 0; | ||
| 407 | enum_id = 0; | ||
| 408 | field = 0; | ||
| 409 | value = 0; | ||
| 410 | while (1) { | ||
| 411 | pos = sh_pfc_gpio_to_enum(pfc, gpio, pos, &enum_id); | ||
| 412 | if (pos <= 0) | ||
| 413 | goto out_err; | ||
| 414 | |||
| 415 | if (!enum_id) | ||
| 416 | break; | ||
| 417 | |||
| 418 | /* first check if this is a function enum */ | ||
| 419 | in_range = sh_pfc_enum_in_range(enum_id, &pfc->pdata->function); | ||
| 420 | if (!in_range) { | ||
| 421 | /* not a function enum */ | ||
| 422 | if (range) { | ||
| 423 | /* | ||
| 424 | * other range exists, so this pin is | ||
| 425 | * a regular GPIO pin that now is being | ||
| 426 | * bound to a specific direction. | ||
| 427 | * | ||
| 428 | * for this case we only allow function enums | ||
| 429 | * and the enums that match the other range. | ||
| 430 | */ | ||
| 431 | in_range = sh_pfc_enum_in_range(enum_id, range); | ||
| 432 | |||
| 433 | /* | ||
| 434 | * special case pass through for fixed | ||
| 435 | * input-only or output-only pins without | ||
| 436 | * function enum register association. | ||
| 437 | */ | ||
| 438 | if (in_range && enum_id == range->force) | ||
| 439 | continue; | ||
| 440 | } else { | ||
| 441 | /* | ||
| 442 | * no other range exists, so this pin | ||
| 443 | * must then be of the function type. | ||
| 444 | * | ||
| 445 | * allow function type pins to select | ||
| 446 | * any combination of function/in/out | ||
| 447 | * in their MARK lists. | ||
| 448 | */ | ||
| 449 | in_range = 1; | ||
| 450 | } | ||
| 451 | } | ||
| 452 | |||
| 453 | if (!in_range) | ||
| 454 | continue; | ||
| 455 | |||
| 456 | if (sh_pfc_get_config_reg(pfc, enum_id, &cr, | ||
| 457 | &field, &value, &cntp) != 0) | ||
| 458 | goto out_err; | ||
| 459 | |||
| 460 | switch (cfg_mode) { | ||
| 461 | case GPIO_CFG_DRYRUN: | ||
| 462 | if (!*cntp || | ||
| 463 | (sh_pfc_read_config_reg(pfc, cr, field) != value)) | ||
| 464 | continue; | ||
| 465 | break; | ||
| 466 | |||
| 467 | case GPIO_CFG_REQ: | ||
| 468 | sh_pfc_write_config_reg(pfc, cr, field, value); | ||
| 469 | *cntp = *cntp + 1; | ||
| 470 | break; | ||
| 471 | |||
| 472 | case GPIO_CFG_FREE: | ||
| 473 | *cntp = *cntp - 1; | ||
| 474 | break; | ||
| 475 | } | ||
| 476 | } | ||
| 477 | |||
| 478 | return 0; | ||
| 479 | out_err: | ||
| 480 | return -1; | ||
| 481 | } | ||
| 482 | |||
| 483 | static int sh_pfc_probe(struct platform_device *pdev) | ||
| 484 | { | ||
| 485 | struct sh_pfc_platform_data *pdata = pdev->dev.platform_data; | ||
| 486 | struct sh_pfc *pfc; | ||
| 487 | int ret; | ||
| 488 | |||
| 489 | /* | ||
| 490 | * Ensure that the type encoding fits | ||
| 491 | */ | ||
| 492 | BUILD_BUG_ON(PINMUX_FLAG_TYPE > ((1 << PINMUX_FLAG_DBIT_SHIFT) - 1)); | ||
| 493 | |||
| 494 | if (pdata == NULL) | ||
| 495 | return -ENODEV; | ||
| 496 | |||
| 497 | pfc = devm_kzalloc(&pdev->dev, sizeof(pfc), GFP_KERNEL); | ||
| 498 | if (pfc == NULL) | ||
| 499 | return -ENOMEM; | ||
| 500 | |||
| 501 | pfc->pdata = pdata; | ||
| 502 | pfc->dev = &pdev->dev; | ||
| 503 | |||
| 504 | ret = sh_pfc_ioremap(pfc, pdev); | ||
| 505 | if (unlikely(ret < 0)) | ||
| 506 | return ret; | ||
| 507 | |||
| 508 | spin_lock_init(&pfc->lock); | ||
| 509 | |||
| 510 | pinctrl_provide_dummies(); | ||
| 511 | sh_pfc_setup_data_regs(pfc); | ||
| 512 | |||
| 513 | /* | ||
| 514 | * Initialize pinctrl bindings first | ||
| 515 | */ | ||
| 516 | ret = sh_pfc_register_pinctrl(pfc); | ||
| 517 | if (unlikely(ret != 0)) | ||
| 518 | return ret; | ||
| 519 | |||
| 520 | #ifdef CONFIG_GPIO_SH_PFC | ||
| 521 | /* | ||
| 522 | * Then the GPIO chip | ||
| 523 | */ | ||
| 524 | ret = sh_pfc_register_gpiochip(pfc); | ||
| 525 | if (unlikely(ret != 0)) { | ||
| 526 | /* | ||
| 527 | * If the GPIO chip fails to come up we still leave the | ||
| 528 | * PFC state as it is, given that there are already | ||
| 529 | * extant users of it that have succeeded by this point. | ||
| 530 | */ | ||
| 531 | pr_notice("failed to init GPIO chip, ignoring...\n"); | ||
| 532 | } | ||
| 533 | #endif | ||
| 534 | |||
| 535 | platform_set_drvdata(pdev, pfc); | ||
| 536 | |||
| 537 | pr_info("%s support registered\n", pdata->name); | ||
| 538 | |||
| 539 | return 0; | ||
| 540 | } | ||
| 541 | |||
| 542 | static int sh_pfc_remove(struct platform_device *pdev) | ||
| 543 | { | ||
| 544 | struct sh_pfc *pfc = platform_get_drvdata(pdev); | ||
| 545 | |||
| 546 | #ifdef CONFIG_GPIO_SH_PFC | ||
| 547 | sh_pfc_unregister_gpiochip(pfc); | ||
| 548 | #endif | ||
| 549 | sh_pfc_unregister_pinctrl(pfc); | ||
| 550 | |||
| 551 | platform_set_drvdata(pdev, NULL); | ||
| 552 | |||
| 553 | return 0; | ||
| 554 | } | ||
| 555 | |||
| 556 | static const struct platform_device_id sh_pfc_id_table[] = { | ||
| 557 | { "sh-pfc", 0 }, | ||
| 558 | { }, | ||
| 559 | }; | ||
| 560 | MODULE_DEVICE_TABLE(platform, sh_pfc_id_table); | ||
| 561 | |||
| 562 | static struct platform_driver sh_pfc_driver = { | ||
| 563 | .probe = sh_pfc_probe, | ||
| 564 | .remove = sh_pfc_remove, | ||
| 565 | .id_table = sh_pfc_id_table, | ||
| 566 | .driver = { | ||
| 567 | .name = DRV_NAME, | ||
| 568 | .owner = THIS_MODULE, | ||
| 569 | }, | ||
| 570 | }; | ||
| 571 | |||
| 572 | static int __init sh_pfc_init(void) | ||
| 573 | { | ||
| 574 | return platform_driver_register(&sh_pfc_driver); | ||
| 575 | } | ||
| 576 | postcore_initcall(sh_pfc_init); | ||
| 577 | |||
| 578 | static void __exit sh_pfc_exit(void) | ||
| 579 | { | ||
| 580 | platform_driver_unregister(&sh_pfc_driver); | ||
| 581 | } | ||
| 582 | module_exit(sh_pfc_exit); | ||
| 583 | |||
| 584 | MODULE_AUTHOR("Magnus Damm, Paul Mundt, Laurent Pinchart"); | ||
| 585 | MODULE_DESCRIPTION("Pin Control and GPIO driver for SuperH pin function controller"); | ||
| 586 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/sh/pfc/core.h b/drivers/sh/pfc/core.h deleted file mode 100644 index 87ae5fd2a201..000000000000 --- a/drivers/sh/pfc/core.h +++ /dev/null | |||
| @@ -1,54 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * SuperH Pin Function Controller support. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Renesas Solutions Corp. | ||
| 5 | * | ||
| 6 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 7 | * License. See the file "COPYING" in the main directory of this archive | ||
| 8 | * for more details. | ||
| 9 | */ | ||
| 10 | #ifndef __SH_PFC_CORE_H__ | ||
| 11 | #define __SH_PFC_CORE_H__ | ||
| 12 | |||
| 13 | #include <linux/compiler.h> | ||
| 14 | #include <linux/sh_pfc.h> | ||
| 15 | #include <linux/types.h> | ||
| 16 | |||
| 17 | struct sh_pfc_window { | ||
| 18 | phys_addr_t phys; | ||
| 19 | void __iomem *virt; | ||
| 20 | unsigned long size; | ||
| 21 | }; | ||
| 22 | |||
| 23 | struct sh_pfc_chip; | ||
| 24 | struct sh_pfc_pinctrl; | ||
| 25 | |||
| 26 | struct sh_pfc { | ||
| 27 | struct device *dev; | ||
| 28 | struct sh_pfc_platform_data *pdata; | ||
| 29 | spinlock_t lock; | ||
| 30 | |||
| 31 | unsigned int num_windows; | ||
| 32 | struct sh_pfc_window *window; | ||
| 33 | |||
| 34 | struct sh_pfc_chip *gpio; | ||
| 35 | struct sh_pfc_pinctrl *pinctrl; | ||
| 36 | }; | ||
| 37 | |||
| 38 | int sh_pfc_register_gpiochip(struct sh_pfc *pfc); | ||
| 39 | int sh_pfc_unregister_gpiochip(struct sh_pfc *pfc); | ||
| 40 | |||
| 41 | int sh_pfc_register_pinctrl(struct sh_pfc *pfc); | ||
| 42 | int sh_pfc_unregister_pinctrl(struct sh_pfc *pfc); | ||
| 43 | |||
| 44 | int sh_pfc_read_bit(struct pinmux_data_reg *dr, unsigned long in_pos); | ||
| 45 | void sh_pfc_write_bit(struct pinmux_data_reg *dr, unsigned long in_pos, | ||
| 46 | unsigned long value); | ||
| 47 | int sh_pfc_get_data_reg(struct sh_pfc *pfc, unsigned gpio, | ||
| 48 | struct pinmux_data_reg **drp, int *bitp); | ||
| 49 | int sh_pfc_gpio_to_enum(struct sh_pfc *pfc, unsigned gpio, int pos, | ||
| 50 | pinmux_enum_t *enum_idp); | ||
| 51 | int sh_pfc_config_gpio(struct sh_pfc *pfc, unsigned gpio, int pinmux_type, | ||
| 52 | int cfg_mode); | ||
| 53 | |||
| 54 | #endif /* __SH_PFC_CORE_H__ */ | ||
diff --git a/drivers/sh/pfc/gpio.c b/drivers/sh/pfc/gpio.c deleted file mode 100644 index a0454f321710..000000000000 --- a/drivers/sh/pfc/gpio.c +++ /dev/null | |||
| @@ -1,179 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * SuperH Pin Function Controller GPIO driver. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Magnus Damm | ||
| 5 | * Copyright (C) 2009 - 2012 Paul Mundt | ||
| 6 | * | ||
| 7 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 8 | * License. See the file "COPYING" in the main directory of this archive | ||
| 9 | * for more details. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #define pr_fmt(fmt) KBUILD_MODNAME " gpio: " fmt | ||
| 13 | |||
| 14 | #include <linux/device.h> | ||
| 15 | #include <linux/gpio.h> | ||
| 16 | #include <linux/init.h> | ||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/pinctrl/consumer.h> | ||
| 19 | #include <linux/sh_pfc.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | #include <linux/spinlock.h> | ||
| 22 | |||
| 23 | #include "core.h" | ||
| 24 | |||
| 25 | struct sh_pfc_chip { | ||
| 26 | struct sh_pfc *pfc; | ||
| 27 | struct gpio_chip gpio_chip; | ||
| 28 | }; | ||
| 29 | |||
| 30 | static struct sh_pfc_chip *gpio_to_pfc_chip(struct gpio_chip *gc) | ||
| 31 | { | ||
| 32 | return container_of(gc, struct sh_pfc_chip, gpio_chip); | ||
| 33 | } | ||
| 34 | |||
| 35 | static struct sh_pfc *gpio_to_pfc(struct gpio_chip *gc) | ||
| 36 | { | ||
| 37 | return gpio_to_pfc_chip(gc)->pfc; | ||
| 38 | } | ||
| 39 | |||
| 40 | static int sh_gpio_request(struct gpio_chip *gc, unsigned offset) | ||
| 41 | { | ||
| 42 | return pinctrl_request_gpio(offset); | ||
| 43 | } | ||
| 44 | |||
| 45 | static void sh_gpio_free(struct gpio_chip *gc, unsigned offset) | ||
| 46 | { | ||
| 47 | pinctrl_free_gpio(offset); | ||
| 48 | } | ||
| 49 | |||
| 50 | static void sh_gpio_set_value(struct sh_pfc *pfc, unsigned gpio, int value) | ||
| 51 | { | ||
| 52 | struct pinmux_data_reg *dr = NULL; | ||
| 53 | int bit = 0; | ||
| 54 | |||
| 55 | if (sh_pfc_get_data_reg(pfc, gpio, &dr, &bit) != 0) | ||
| 56 | BUG(); | ||
| 57 | else | ||
| 58 | sh_pfc_write_bit(dr, bit, value); | ||
| 59 | } | ||
| 60 | |||
| 61 | static int sh_gpio_get_value(struct sh_pfc *pfc, unsigned gpio) | ||
| 62 | { | ||
| 63 | struct pinmux_data_reg *dr = NULL; | ||
| 64 | int bit = 0; | ||
| 65 | |||
| 66 | if (sh_pfc_get_data_reg(pfc, gpio, &dr, &bit) != 0) | ||
| 67 | return -EINVAL; | ||
| 68 | |||
| 69 | return sh_pfc_read_bit(dr, bit); | ||
| 70 | } | ||
| 71 | |||
| 72 | static int sh_gpio_direction_input(struct gpio_chip *gc, unsigned offset) | ||
| 73 | { | ||
| 74 | return pinctrl_gpio_direction_input(offset); | ||
| 75 | } | ||
| 76 | |||
| 77 | static int sh_gpio_direction_output(struct gpio_chip *gc, unsigned offset, | ||
| 78 | int value) | ||
| 79 | { | ||
| 80 | sh_gpio_set_value(gpio_to_pfc(gc), offset, value); | ||
| 81 | |||
| 82 | return pinctrl_gpio_direction_output(offset); | ||
| 83 | } | ||
| 84 | |||
| 85 | static int sh_gpio_get(struct gpio_chip *gc, unsigned offset) | ||
| 86 | { | ||
| 87 | return sh_gpio_get_value(gpio_to_pfc(gc), offset); | ||
| 88 | } | ||
| 89 | |||
| 90 | static void sh_gpio_set(struct gpio_chip *gc, unsigned offset, int value) | ||
| 91 | { | ||
| 92 | sh_gpio_set_value(gpio_to_pfc(gc), offset, value); | ||
| 93 | } | ||
| 94 | |||
| 95 | static int sh_gpio_to_irq(struct gpio_chip *gc, unsigned offset) | ||
| 96 | { | ||
| 97 | struct sh_pfc *pfc = gpio_to_pfc(gc); | ||
| 98 | pinmux_enum_t enum_id; | ||
| 99 | pinmux_enum_t *enum_ids; | ||
| 100 | int i, k, pos; | ||
| 101 | |||
| 102 | pos = 0; | ||
| 103 | enum_id = 0; | ||
| 104 | while (1) { | ||
| 105 | pos = sh_pfc_gpio_to_enum(pfc, offset, pos, &enum_id); | ||
| 106 | if (pos <= 0 || !enum_id) | ||
| 107 | break; | ||
| 108 | |||
| 109 | for (i = 0; i < pfc->pdata->gpio_irq_size; i++) { | ||
| 110 | enum_ids = pfc->pdata->gpio_irq[i].enum_ids; | ||
| 111 | for (k = 0; enum_ids[k]; k++) { | ||
| 112 | if (enum_ids[k] == enum_id) | ||
| 113 | return pfc->pdata->gpio_irq[i].irq; | ||
| 114 | } | ||
| 115 | } | ||
| 116 | } | ||
| 117 | |||
| 118 | return -ENOSYS; | ||
| 119 | } | ||
| 120 | |||
| 121 | static void sh_pfc_gpio_setup(struct sh_pfc_chip *chip) | ||
| 122 | { | ||
| 123 | struct sh_pfc *pfc = chip->pfc; | ||
| 124 | struct gpio_chip *gc = &chip->gpio_chip; | ||
| 125 | |||
| 126 | gc->request = sh_gpio_request; | ||
| 127 | gc->free = sh_gpio_free; | ||
| 128 | gc->direction_input = sh_gpio_direction_input; | ||
| 129 | gc->get = sh_gpio_get; | ||
| 130 | gc->direction_output = sh_gpio_direction_output; | ||
| 131 | gc->set = sh_gpio_set; | ||
| 132 | gc->to_irq = sh_gpio_to_irq; | ||
| 133 | |||
| 134 | WARN_ON(pfc->pdata->first_gpio != 0); /* needs testing */ | ||
| 135 | |||
| 136 | gc->label = pfc->pdata->name; | ||
| 137 | gc->owner = THIS_MODULE; | ||
| 138 | gc->base = pfc->pdata->first_gpio; | ||
| 139 | gc->ngpio = (pfc->pdata->last_gpio - pfc->pdata->first_gpio) + 1; | ||
| 140 | } | ||
| 141 | |||
| 142 | int sh_pfc_register_gpiochip(struct sh_pfc *pfc) | ||
| 143 | { | ||
| 144 | struct sh_pfc_chip *chip; | ||
| 145 | int ret; | ||
| 146 | |||
| 147 | chip = devm_kzalloc(pfc->dev, sizeof(*chip), GFP_KERNEL); | ||
| 148 | if (unlikely(!chip)) | ||
| 149 | return -ENOMEM; | ||
| 150 | |||
| 151 | chip->pfc = pfc; | ||
| 152 | |||
| 153 | sh_pfc_gpio_setup(chip); | ||
| 154 | |||
| 155 | ret = gpiochip_add(&chip->gpio_chip); | ||
| 156 | if (unlikely(ret < 0)) | ||
| 157 | return ret; | ||
| 158 | |||
| 159 | pfc->gpio = chip; | ||
| 160 | |||
| 161 | pr_info("%s handling gpio %d -> %d\n", | ||
| 162 | pfc->pdata->name, pfc->pdata->first_gpio, | ||
| 163 | pfc->pdata->last_gpio); | ||
| 164 | |||
| 165 | return 0; | ||
| 166 | } | ||
| 167 | |||
| 168 | int sh_pfc_unregister_gpiochip(struct sh_pfc *pfc) | ||
| 169 | { | ||
| 170 | struct sh_pfc_chip *chip = pfc->gpio; | ||
| 171 | int ret; | ||
| 172 | |||
| 173 | ret = gpiochip_remove(&chip->gpio_chip); | ||
| 174 | if (unlikely(ret < 0)) | ||
| 175 | return ret; | ||
| 176 | |||
| 177 | pfc->gpio = NULL; | ||
| 178 | return 0; | ||
| 179 | } | ||
diff --git a/drivers/sh/pfc/pinctrl.c b/drivers/sh/pfc/pinctrl.c deleted file mode 100644 index 221bde03913a..000000000000 --- a/drivers/sh/pfc/pinctrl.c +++ /dev/null | |||
| @@ -1,464 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * SuperH Pin Function Controller pinmux support. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Paul Mundt | ||
| 5 | * | ||
| 6 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 7 | * License. See the file "COPYING" in the main directory of this archive | ||
| 8 | * for more details. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #define DRV_NAME "sh-pfc" | ||
| 12 | #define pr_fmt(fmt) KBUILD_MODNAME " pinctrl: " fmt | ||
| 13 | |||
| 14 | #include <linux/device.h> | ||
| 15 | #include <linux/err.h> | ||
| 16 | #include <linux/init.h> | ||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/pinctrl/consumer.h> | ||
| 19 | #include <linux/pinctrl/pinconf.h> | ||
| 20 | #include <linux/pinctrl/pinconf-generic.h> | ||
| 21 | #include <linux/pinctrl/pinctrl.h> | ||
| 22 | #include <linux/pinctrl/pinmux.h> | ||
| 23 | #include <linux/sh_pfc.h> | ||
| 24 | #include <linux/slab.h> | ||
| 25 | #include <linux/spinlock.h> | ||
| 26 | |||
| 27 | #include "core.h" | ||
| 28 | |||
| 29 | struct sh_pfc_pinctrl { | ||
| 30 | struct pinctrl_dev *pctl; | ||
| 31 | struct sh_pfc *pfc; | ||
| 32 | |||
| 33 | struct pinmux_gpio **functions; | ||
| 34 | unsigned int nr_functions; | ||
| 35 | |||
| 36 | struct pinctrl_pin_desc *pads; | ||
| 37 | unsigned int nr_pads; | ||
| 38 | |||
| 39 | spinlock_t lock; | ||
| 40 | }; | ||
| 41 | |||
| 42 | static int sh_pfc_get_groups_count(struct pinctrl_dev *pctldev) | ||
| 43 | { | ||
| 44 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
| 45 | |||
| 46 | return pmx->nr_pads; | ||
| 47 | } | ||
| 48 | |||
| 49 | static const char *sh_pfc_get_group_name(struct pinctrl_dev *pctldev, | ||
| 50 | unsigned selector) | ||
| 51 | { | ||
| 52 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
| 53 | |||
| 54 | return pmx->pads[selector].name; | ||
| 55 | } | ||
| 56 | |||
| 57 | static int sh_pfc_get_group_pins(struct pinctrl_dev *pctldev, unsigned group, | ||
| 58 | const unsigned **pins, unsigned *num_pins) | ||
| 59 | { | ||
| 60 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
| 61 | |||
| 62 | *pins = &pmx->pads[group].number; | ||
| 63 | *num_pins = 1; | ||
| 64 | |||
| 65 | return 0; | ||
| 66 | } | ||
| 67 | |||
| 68 | static void sh_pfc_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, | ||
| 69 | unsigned offset) | ||
| 70 | { | ||
| 71 | seq_printf(s, "%s", DRV_NAME); | ||
| 72 | } | ||
| 73 | |||
| 74 | static struct pinctrl_ops sh_pfc_pinctrl_ops = { | ||
| 75 | .get_groups_count = sh_pfc_get_groups_count, | ||
| 76 | .get_group_name = sh_pfc_get_group_name, | ||
| 77 | .get_group_pins = sh_pfc_get_group_pins, | ||
| 78 | .pin_dbg_show = sh_pfc_pin_dbg_show, | ||
| 79 | }; | ||
| 80 | |||
| 81 | static int sh_pfc_get_functions_count(struct pinctrl_dev *pctldev) | ||
| 82 | { | ||
| 83 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
| 84 | |||
| 85 | return pmx->nr_functions; | ||
| 86 | } | ||
| 87 | |||
| 88 | static const char *sh_pfc_get_function_name(struct pinctrl_dev *pctldev, | ||
| 89 | unsigned selector) | ||
| 90 | { | ||
| 91 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
| 92 | |||
| 93 | return pmx->functions[selector]->name; | ||
| 94 | } | ||
| 95 | |||
| 96 | static int sh_pfc_get_function_groups(struct pinctrl_dev *pctldev, unsigned func, | ||
| 97 | const char * const **groups, | ||
| 98 | unsigned * const num_groups) | ||
| 99 | { | ||
| 100 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
| 101 | |||
| 102 | *groups = &pmx->functions[func]->name; | ||
| 103 | *num_groups = 1; | ||
| 104 | |||
| 105 | return 0; | ||
| 106 | } | ||
| 107 | |||
| 108 | static int sh_pfc_noop_enable(struct pinctrl_dev *pctldev, unsigned func, | ||
| 109 | unsigned group) | ||
| 110 | { | ||
| 111 | return 0; | ||
| 112 | } | ||
| 113 | |||
| 114 | static void sh_pfc_noop_disable(struct pinctrl_dev *pctldev, unsigned func, | ||
| 115 | unsigned group) | ||
| 116 | { | ||
| 117 | } | ||
| 118 | |||
| 119 | static int sh_pfc_config_function(struct sh_pfc *pfc, unsigned offset) | ||
| 120 | { | ||
| 121 | if (sh_pfc_config_gpio(pfc, offset, | ||
| 122 | PINMUX_TYPE_FUNCTION, | ||
| 123 | GPIO_CFG_DRYRUN) != 0) | ||
| 124 | return -EINVAL; | ||
| 125 | |||
| 126 | if (sh_pfc_config_gpio(pfc, offset, | ||
| 127 | PINMUX_TYPE_FUNCTION, | ||
| 128 | GPIO_CFG_REQ) != 0) | ||
| 129 | return -EINVAL; | ||
| 130 | |||
| 131 | return 0; | ||
| 132 | } | ||
| 133 | |||
| 134 | static int sh_pfc_reconfig_pin(struct sh_pfc *pfc, unsigned offset, | ||
| 135 | int new_type) | ||
| 136 | { | ||
| 137 | unsigned long flags; | ||
| 138 | int pinmux_type; | ||
| 139 | int ret = -EINVAL; | ||
| 140 | |||
| 141 | spin_lock_irqsave(&pfc->lock, flags); | ||
| 142 | |||
| 143 | pinmux_type = pfc->pdata->gpios[offset].flags & PINMUX_FLAG_TYPE; | ||
| 144 | |||
| 145 | /* | ||
| 146 | * See if the present config needs to first be de-configured. | ||
| 147 | */ | ||
| 148 | switch (pinmux_type) { | ||
| 149 | case PINMUX_TYPE_GPIO: | ||
| 150 | break; | ||
| 151 | case PINMUX_TYPE_OUTPUT: | ||
| 152 | case PINMUX_TYPE_INPUT: | ||
| 153 | case PINMUX_TYPE_INPUT_PULLUP: | ||
| 154 | case PINMUX_TYPE_INPUT_PULLDOWN: | ||
| 155 | sh_pfc_config_gpio(pfc, offset, pinmux_type, GPIO_CFG_FREE); | ||
| 156 | break; | ||
| 157 | default: | ||
| 158 | goto err; | ||
| 159 | } | ||
| 160 | |||
| 161 | /* | ||
| 162 | * Dry run | ||
| 163 | */ | ||
| 164 | if (sh_pfc_config_gpio(pfc, offset, new_type, | ||
| 165 | GPIO_CFG_DRYRUN) != 0) | ||
| 166 | goto err; | ||
| 167 | |||
| 168 | /* | ||
| 169 | * Request | ||
| 170 | */ | ||
| 171 | if (sh_pfc_config_gpio(pfc, offset, new_type, | ||
| 172 | GPIO_CFG_REQ) != 0) | ||
| 173 | goto err; | ||
| 174 | |||
| 175 | pfc->pdata->gpios[offset].flags &= ~PINMUX_FLAG_TYPE; | ||
| 176 | pfc->pdata->gpios[offset].flags |= new_type; | ||
| 177 | |||
| 178 | ret = 0; | ||
| 179 | |||
| 180 | err: | ||
| 181 | spin_unlock_irqrestore(&pfc->lock, flags); | ||
| 182 | |||
| 183 | return ret; | ||
| 184 | } | ||
| 185 | |||
| 186 | |||
| 187 | static int sh_pfc_gpio_request_enable(struct pinctrl_dev *pctldev, | ||
| 188 | struct pinctrl_gpio_range *range, | ||
| 189 | unsigned offset) | ||
| 190 | { | ||
| 191 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
| 192 | struct sh_pfc *pfc = pmx->pfc; | ||
| 193 | unsigned long flags; | ||
| 194 | int ret, pinmux_type; | ||
| 195 | |||
| 196 | spin_lock_irqsave(&pfc->lock, flags); | ||
| 197 | |||
| 198 | pinmux_type = pfc->pdata->gpios[offset].flags & PINMUX_FLAG_TYPE; | ||
| 199 | |||
| 200 | switch (pinmux_type) { | ||
| 201 | case PINMUX_TYPE_FUNCTION: | ||
| 202 | pr_notice_once("Use of GPIO API for function requests is " | ||
| 203 | "deprecated, convert to pinctrl\n"); | ||
| 204 | /* handle for now */ | ||
| 205 | ret = sh_pfc_config_function(pfc, offset); | ||
| 206 | if (unlikely(ret < 0)) | ||
| 207 | goto err; | ||
| 208 | |||
| 209 | break; | ||
| 210 | case PINMUX_TYPE_GPIO: | ||
| 211 | case PINMUX_TYPE_INPUT: | ||
| 212 | case PINMUX_TYPE_OUTPUT: | ||
| 213 | break; | ||
| 214 | default: | ||
| 215 | pr_err("Unsupported mux type (%d), bailing...\n", pinmux_type); | ||
| 216 | ret = -ENOTSUPP; | ||
| 217 | goto err; | ||
| 218 | } | ||
| 219 | |||
| 220 | ret = 0; | ||
| 221 | |||
| 222 | err: | ||
| 223 | spin_unlock_irqrestore(&pfc->lock, flags); | ||
| 224 | |||
| 225 | return ret; | ||
| 226 | } | ||
| 227 | |||
| 228 | static void sh_pfc_gpio_disable_free(struct pinctrl_dev *pctldev, | ||
| 229 | struct pinctrl_gpio_range *range, | ||
| 230 | unsigned offset) | ||
| 231 | { | ||
| 232 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
| 233 | struct sh_pfc *pfc = pmx->pfc; | ||
| 234 | unsigned long flags; | ||
| 235 | int pinmux_type; | ||
| 236 | |||
| 237 | spin_lock_irqsave(&pfc->lock, flags); | ||
| 238 | |||
| 239 | pinmux_type = pfc->pdata->gpios[offset].flags & PINMUX_FLAG_TYPE; | ||
| 240 | |||
| 241 | sh_pfc_config_gpio(pfc, offset, pinmux_type, GPIO_CFG_FREE); | ||
| 242 | |||
| 243 | spin_unlock_irqrestore(&pfc->lock, flags); | ||
| 244 | } | ||
| 245 | |||
| 246 | static int sh_pfc_gpio_set_direction(struct pinctrl_dev *pctldev, | ||
| 247 | struct pinctrl_gpio_range *range, | ||
| 248 | unsigned offset, bool input) | ||
| 249 | { | ||
| 250 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
| 251 | int type = input ? PINMUX_TYPE_INPUT : PINMUX_TYPE_OUTPUT; | ||
| 252 | |||
| 253 | return sh_pfc_reconfig_pin(pmx->pfc, offset, type); | ||
| 254 | } | ||
| 255 | |||
| 256 | static struct pinmux_ops sh_pfc_pinmux_ops = { | ||
| 257 | .get_functions_count = sh_pfc_get_functions_count, | ||
| 258 | .get_function_name = sh_pfc_get_function_name, | ||
| 259 | .get_function_groups = sh_pfc_get_function_groups, | ||
| 260 | .enable = sh_pfc_noop_enable, | ||
| 261 | .disable = sh_pfc_noop_disable, | ||
| 262 | .gpio_request_enable = sh_pfc_gpio_request_enable, | ||
| 263 | .gpio_disable_free = sh_pfc_gpio_disable_free, | ||
| 264 | .gpio_set_direction = sh_pfc_gpio_set_direction, | ||
| 265 | }; | ||
| 266 | |||
| 267 | static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin, | ||
| 268 | unsigned long *config) | ||
| 269 | { | ||
| 270 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
| 271 | struct sh_pfc *pfc = pmx->pfc; | ||
| 272 | |||
| 273 | *config = pfc->pdata->gpios[pin].flags & PINMUX_FLAG_TYPE; | ||
| 274 | |||
| 275 | return 0; | ||
| 276 | } | ||
| 277 | |||
| 278 | static int sh_pfc_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin, | ||
| 279 | unsigned long config) | ||
| 280 | { | ||
| 281 | struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); | ||
| 282 | |||
| 283 | /* Validate the new type */ | ||
| 284 | if (config >= PINMUX_FLAG_TYPE) | ||
| 285 | return -EINVAL; | ||
| 286 | |||
| 287 | return sh_pfc_reconfig_pin(pmx->pfc, pin, config); | ||
| 288 | } | ||
| 289 | |||
| 290 | static void sh_pfc_pinconf_dbg_show(struct pinctrl_dev *pctldev, | ||
| 291 | struct seq_file *s, unsigned pin) | ||
| 292 | { | ||
| 293 | const char *pinmux_type_str[] = { | ||
| 294 | [PINMUX_TYPE_NONE] = "none", | ||
| 295 | [PINMUX_TYPE_FUNCTION] = "function", | ||
| 296 | [PINMUX_TYPE_GPIO] = "gpio", | ||
| 297 | [PINMUX_TYPE_OUTPUT] = "output", | ||
| 298 | [PINMUX_TYPE_INPUT] = "input", | ||
| 299 | [PINMUX_TYPE_INPUT_PULLUP] = "input bias pull up", | ||
| 300 | [PINMUX_TYPE_INPUT_PULLDOWN] = "input bias pull down", | ||
| 301 | }; | ||
| 302 | unsigned long config; | ||
| 303 | int rc; | ||
| 304 | |||
| 305 | rc = sh_pfc_pinconf_get(pctldev, pin, &config); | ||
| 306 | if (unlikely(rc != 0)) | ||
| 307 | return; | ||
| 308 | |||
| 309 | seq_printf(s, " %s", pinmux_type_str[config]); | ||
| 310 | } | ||
| 311 | |||
| 312 | static struct pinconf_ops sh_pfc_pinconf_ops = { | ||
| 313 | .pin_config_get = sh_pfc_pinconf_get, | ||
| 314 | .pin_config_set = sh_pfc_pinconf_set, | ||
| 315 | .pin_config_dbg_show = sh_pfc_pinconf_dbg_show, | ||
| 316 | }; | ||
| 317 | |||
| 318 | static struct pinctrl_gpio_range sh_pfc_gpio_range = { | ||
| 319 | .name = DRV_NAME, | ||
| 320 | .id = 0, | ||
| 321 | }; | ||
| 322 | |||
| 323 | static struct pinctrl_desc sh_pfc_pinctrl_desc = { | ||
| 324 | .name = DRV_NAME, | ||
| 325 | .owner = THIS_MODULE, | ||
| 326 | .pctlops = &sh_pfc_pinctrl_ops, | ||
| 327 | .pmxops = &sh_pfc_pinmux_ops, | ||
| 328 | .confops = &sh_pfc_pinconf_ops, | ||
| 329 | }; | ||
| 330 | |||
| 331 | static void sh_pfc_map_one_gpio(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx, | ||
| 332 | struct pinmux_gpio *gpio, unsigned offset) | ||
| 333 | { | ||
| 334 | struct pinmux_data_reg *dummy; | ||
| 335 | unsigned long flags; | ||
| 336 | int bit; | ||
| 337 | |||
| 338 | gpio->flags &= ~PINMUX_FLAG_TYPE; | ||
| 339 | |||
| 340 | if (sh_pfc_get_data_reg(pfc, offset, &dummy, &bit) == 0) | ||
| 341 | gpio->flags |= PINMUX_TYPE_GPIO; | ||
| 342 | else { | ||
| 343 | gpio->flags |= PINMUX_TYPE_FUNCTION; | ||
| 344 | |||
| 345 | spin_lock_irqsave(&pmx->lock, flags); | ||
| 346 | pmx->nr_functions++; | ||
| 347 | spin_unlock_irqrestore(&pmx->lock, flags); | ||
| 348 | } | ||
| 349 | } | ||
| 350 | |||
| 351 | /* pinmux ranges -> pinctrl pin descs */ | ||
| 352 | static int sh_pfc_map_gpios(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx) | ||
| 353 | { | ||
| 354 | unsigned long flags; | ||
| 355 | int i; | ||
| 356 | |||
| 357 | pmx->nr_pads = pfc->pdata->last_gpio - pfc->pdata->first_gpio + 1; | ||
| 358 | |||
| 359 | pmx->pads = devm_kzalloc(pfc->dev, sizeof(*pmx->pads) * pmx->nr_pads, | ||
| 360 | GFP_KERNEL); | ||
| 361 | if (unlikely(!pmx->pads)) { | ||
| 362 | pmx->nr_pads = 0; | ||
| 363 | return -ENOMEM; | ||
| 364 | } | ||
| 365 | |||
| 366 | spin_lock_irqsave(&pfc->lock, flags); | ||
| 367 | |||
| 368 | /* | ||
| 369 | * We don't necessarily have a 1:1 mapping between pin and linux | ||
| 370 | * GPIO number, as the latter maps to the associated enum_id. | ||
| 371 | * Care needs to be taken to translate back to pin space when | ||
| 372 | * dealing with any pin configurations. | ||
| 373 | */ | ||
| 374 | for (i = 0; i < pmx->nr_pads; i++) { | ||
| 375 | struct pinctrl_pin_desc *pin = pmx->pads + i; | ||
| 376 | struct pinmux_gpio *gpio = pfc->pdata->gpios + i; | ||
| 377 | |||
| 378 | pin->number = pfc->pdata->first_gpio + i; | ||
| 379 | pin->name = gpio->name; | ||
| 380 | |||
| 381 | /* XXX */ | ||
| 382 | if (unlikely(!gpio->enum_id)) | ||
| 383 | continue; | ||
| 384 | |||
| 385 | sh_pfc_map_one_gpio(pfc, pmx, gpio, i); | ||
| 386 | } | ||
| 387 | |||
| 388 | spin_unlock_irqrestore(&pfc->lock, flags); | ||
| 389 | |||
| 390 | sh_pfc_pinctrl_desc.pins = pmx->pads; | ||
| 391 | sh_pfc_pinctrl_desc.npins = pmx->nr_pads; | ||
| 392 | |||
| 393 | return 0; | ||
| 394 | } | ||
| 395 | |||
| 396 | static int sh_pfc_map_functions(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx) | ||
| 397 | { | ||
| 398 | unsigned long flags; | ||
| 399 | int i, fn; | ||
| 400 | |||
| 401 | pmx->functions = devm_kzalloc(pfc->dev, pmx->nr_functions * | ||
| 402 | sizeof(*pmx->functions), GFP_KERNEL); | ||
| 403 | if (unlikely(!pmx->functions)) | ||
| 404 | return -ENOMEM; | ||
| 405 | |||
| 406 | spin_lock_irqsave(&pmx->lock, flags); | ||
| 407 | |||
| 408 | for (i = fn = 0; i < pmx->nr_pads; i++) { | ||
| 409 | struct pinmux_gpio *gpio = pfc->pdata->gpios + i; | ||
| 410 | |||
| 411 | if ((gpio->flags & PINMUX_FLAG_TYPE) == PINMUX_TYPE_FUNCTION) | ||
| 412 | pmx->functions[fn++] = gpio; | ||
| 413 | } | ||
| 414 | |||
| 415 | spin_unlock_irqrestore(&pmx->lock, flags); | ||
| 416 | |||
| 417 | return 0; | ||
| 418 | } | ||
| 419 | |||
| 420 | int sh_pfc_register_pinctrl(struct sh_pfc *pfc) | ||
| 421 | { | ||
| 422 | struct sh_pfc_pinctrl *pmx; | ||
| 423 | int ret; | ||
| 424 | |||
| 425 | pmx = devm_kzalloc(pfc->dev, sizeof(*pmx), GFP_KERNEL); | ||
| 426 | if (unlikely(!pmx)) | ||
| 427 | return -ENOMEM; | ||
| 428 | |||
| 429 | spin_lock_init(&pmx->lock); | ||
| 430 | |||
| 431 | pmx->pfc = pfc; | ||
| 432 | pfc->pinctrl = pmx; | ||
| 433 | |||
| 434 | ret = sh_pfc_map_gpios(pfc, pmx); | ||
| 435 | if (unlikely(ret != 0)) | ||
| 436 | return ret; | ||
| 437 | |||
| 438 | ret = sh_pfc_map_functions(pfc, pmx); | ||
| 439 | if (unlikely(ret != 0)) | ||
| 440 | return ret; | ||
| 441 | |||
| 442 | pmx->pctl = pinctrl_register(&sh_pfc_pinctrl_desc, pfc->dev, pmx); | ||
| 443 | if (IS_ERR(pmx->pctl)) | ||
| 444 | return PTR_ERR(pmx->pctl); | ||
| 445 | |||
| 446 | sh_pfc_gpio_range.npins = pfc->pdata->last_gpio | ||
| 447 | - pfc->pdata->first_gpio + 1; | ||
| 448 | sh_pfc_gpio_range.base = pfc->pdata->first_gpio; | ||
| 449 | sh_pfc_gpio_range.pin_base = pfc->pdata->first_gpio; | ||
| 450 | |||
| 451 | pinctrl_add_gpio_range(pmx->pctl, &sh_pfc_gpio_range); | ||
| 452 | |||
| 453 | return 0; | ||
| 454 | } | ||
| 455 | |||
| 456 | int sh_pfc_unregister_pinctrl(struct sh_pfc *pfc) | ||
| 457 | { | ||
| 458 | struct sh_pfc_pinctrl *pmx = pfc->pinctrl; | ||
| 459 | |||
| 460 | pinctrl_unregister(pmx->pctl); | ||
| 461 | |||
| 462 | pfc->pinctrl = NULL; | ||
| 463 | return 0; | ||
| 464 | } | ||
