| 1 | |
| 2 | |
| 3 | * SP7021 Pin Controller Driver.
|
| 4 | * Copyright (C) Sunplus Tech / Tibbo Tech.
|
| 5 |
|
| 6 |
|
| 7 | #include <linux/cleanup.h>
|
| 8 | #include <linux/bitfield.h>
|
| 9 | #include <linux/device.h>
|
| 10 | #include <linux/err.h>
|
| 11 | #include <linux/gpio/driver.h>
|
| 12 | #include <linux/init.h>
|
| 13 | #include <linux/module.h>
|
| 14 | #include <linux/of.h>
|
| 15 | #include <linux/overflow.h>
|
| 16 | #include <linux/platform_device.h>
|
| 17 | #include <linux/seq_file.h>
|
| 18 | #include <linux/slab.h>
|
| 19 |
|
| 20 | #include <linux/pinctrl/pinconf.h>
|
| 21 | #include <linux/pinctrl/pinconf-generic.h>
|
| 22 | #include <linux/pinctrl/pinmux.h>
|
| 23 |
|
| 24 | #include <dt-bindings/pinctrl/sppctl-sp7021.h>
|
| 25 |
|
| 26 | #include "../core.h"
|
| 27 | #include "../pinctrl-utils.h"
|
| 28 |
|
| 29 | #include "sppctl.h"
|
| 30 |
|
| 31 | struct sppctl_gpio_chip {
|
| 32 | void __iomem *gpioxt_base;
|
| 33 | void __iomem *first_base;
|
| 34 |
|
| 35 | struct gpio_chip chip;
|
| 36 | spinlock_t lock;
|
| 37 | };
|
| 38 |
|
| 39 | static inline u32 sppctl_first_readl(struct sppctl_gpio_chip *spp_gchip, u32 off)
|
| 40 | {
|
| 41 | return readl(spp_gchip->first_base + SPPCTL_GPIO_OFF_FIRST + off);
|
| 42 | }
|
| 43 |
|
| 44 | static inline void sppctl_first_writel(struct sppctl_gpio_chip *spp_gchip, u32 val, u32 off)
|
| 45 | {
|
| 46 | writel(val, spp_gchip->first_base + SPPCTL_GPIO_OFF_FIRST + off);
|
| 47 | }
|
| 48 |
|
| 49 | static inline u32 sppctl_gpio_master_readl(struct sppctl_gpio_chip *spp_gchip, u32 off)
|
| 50 | {
|
| 51 | return readl(spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_MASTER + off);
|
| 52 | }
|
| 53 |
|
| 54 | static inline void sppctl_gpio_master_writel(struct sppctl_gpio_chip *spp_gchip, u32 val,
|
| 55 | u32 off)
|
| 56 | {
|
| 57 | writel(val, spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_MASTER + off);
|
| 58 | }
|
| 59 |
|
| 60 | static inline u32 sppctl_gpio_oe_readl(struct sppctl_gpio_chip *spp_gchip, u32 off)
|
| 61 | {
|
| 62 | return readl(spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_OE + off);
|
| 63 | }
|
| 64 |
|
| 65 | static inline void sppctl_gpio_oe_writel(struct sppctl_gpio_chip *spp_gchip, u32 val, u32 off)
|
| 66 | {
|
| 67 | writel(val, spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_OE + off);
|
| 68 | }
|
| 69 |
|
| 70 | static inline void sppctl_gpio_out_writel(struct sppctl_gpio_chip *spp_gchip, u32 val, u32 off)
|
| 71 | {
|
| 72 | writel(val, spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_OUT + off);
|
| 73 | }
|
| 74 |
|
| 75 | static inline u32 sppctl_gpio_in_readl(struct sppctl_gpio_chip *spp_gchip, u32 off)
|
| 76 | {
|
| 77 | return readl(spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_IN + off);
|
| 78 | }
|
| 79 |
|
| 80 | static inline u32 sppctl_gpio_iinv_readl(struct sppctl_gpio_chip *spp_gchip, u32 off)
|
| 81 | {
|
| 82 | return readl(spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_IINV + off);
|
| 83 | }
|
| 84 |
|
| 85 | static inline void sppctl_gpio_iinv_writel(struct sppctl_gpio_chip *spp_gchip, u32 val,
|
| 86 | u32 off)
|
| 87 | {
|
| 88 | writel(val, spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_IINV + off);
|
| 89 | }
|
| 90 |
|
| 91 | static inline u32 sppctl_gpio_oinv_readl(struct sppctl_gpio_chip *spp_gchip, u32 off)
|
| 92 | {
|
| 93 | return readl(spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_OINV + off);
|
| 94 | }
|
| 95 |
|
| 96 | static inline void sppctl_gpio_oinv_writel(struct sppctl_gpio_chip *spp_gchip, u32 val,
|
| 97 | u32 off)
|
| 98 | {
|
| 99 | writel(val, spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_OINV + off);
|
| 100 | }
|
| 101 |
|
| 102 | static inline u32 sppctl_gpio_od_readl(struct sppctl_gpio_chip *spp_gchip, u32 off)
|
| 103 | {
|
| 104 | return readl(spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_OD + off);
|
| 105 | }
|
| 106 |
|
| 107 | static inline void sppctl_gpio_od_writel(struct sppctl_gpio_chip *spp_gchip, u32 val, u32 off)
|
| 108 | {
|
| 109 | writel(val, spp_gchip->gpioxt_base + SPPCTL_GPIO_OFF_OD + off);
|
| 110 | }
|
| 111 |
|
| 112 | static inline u32 sppctl_get_reg_and_bit_offset(unsigned int offset, u32 *reg_off)
|
| 113 | {
|
| 114 | u32 bit_off;
|
| 115 |
|
| 116 |
|
| 117 | *reg_off = (offset / 32) * 4;
|
| 118 | bit_off = offset % 32;
|
| 119 |
|
| 120 | return bit_off;
|
| 121 | }
|
| 122 |
|
| 123 | static inline u32 sppctl_get_moon_reg_and_bit_offset(unsigned int offset, u32 *reg_off)
|
| 124 | {
|
| 125 | u32 bit_off;
|
| 126 |
|
| 127 | |
| 128 | * Each MOON register has 32 bits. Upper 16-bit word are mask-fields.
|
| 129 | * The lower 16-bit word are the control-fields. The corresponding
|
| 130 | * bits in mask-field should be set then you can write something to
|
| 131 | * control-field.
|
| 132 |
|
| 133 | *reg_off = (offset / 16) * 4;
|
| 134 | bit_off = offset % 16;
|
| 135 |
|
| 136 | return bit_off;
|
| 137 | }
|
| 138 |
|
| 139 | static inline u32 sppctl_prep_moon_reg_and_offset(unsigned int offset, u32 *reg_off, int val)
|
| 140 | {
|
| 141 | u32 bit_off;
|
| 142 |
|
| 143 | bit_off = sppctl_get_moon_reg_and_bit_offset(offset, reg_off);
|
| 144 | if (val)
|
| 145 | return SPPCTL_SET_MOON_REG_BIT(bit_off);
|
| 146 | else
|
| 147 | return SPPCTL_CLR_MOON_REG_BIT(bit_off);
|
| 148 | }
|
| 149 |
|
| 150 | |
| 151 | * sppctl_func_set() - Set pin of fully-pinmux function.
|
| 152 | *
|
| 153 | * Mask-fields and control-fields of fully-pinmux function of SP7021 are
|
| 154 | * arranged as shown below:
|
| 155 | *
|
| 156 | * func# | register | mask-field | control-field
|
| 157 | * -------+----------+--------------+---------------
|
| 158 | * 0 | base[0] | (22 : 16) | ( 6 : 0)
|
| 159 | * 1 | base[0] | (30 : 24) | (14 : 8)
|
| 160 | * 2 | base[1] | (22 : 16) | ( 6 : 0)
|
| 161 | * 3 | baeg[1] | (30 : 24) | (14 : 8)
|
| 162 | * : | : | : | :
|
| 163 | *
|
| 164 | * where mask-fields are used to protect control-fields from write-in
|
| 165 | * accidentally. Set the corresponding bits in the mask-field before
|
| 166 | * you write a value into a control-field.
|
| 167 | *
|
| 168 | * Control-fields are used to set where the function pin is going to
|
| 169 | * be routed to.
|
| 170 | *
|
| 171 | * Note that mask-fields and control-fields of even number of 'func'
|
| 172 | * are located at bits (22:16) and (6:0), while odd number of 'func's
|
| 173 | * are located at bits (30:24) and (14:8).
|
| 174 |
|
| 175 | static void sppctl_func_set(struct sppctl_pdata *pctl, u8 func, u8 val)
|
| 176 | {
|
| 177 | u32 reg, offset;
|
| 178 |
|
| 179 | |
| 180 | * Note that upper 16-bit word are mask-fields and lower 16-bit
|
| 181 | * word are the control-fields. Set corresponding bits in mask-
|
| 182 | * field before write to a control-field.
|
| 183 |
|
| 184 | reg = SPPCTL_FULLY_PINMUX_MASK_MASK | val;
|
| 185 |
|
| 186 | |
| 187 | * MUXF_L2SW_CLK_OUT is the first fully-pinmux pin
|
| 188 | * and its register offset is 0.
|
| 189 |
|
| 190 | func -= MUXF_L2SW_CLK_OUT;
|
| 191 |
|
| 192 | |
| 193 | * Check if 'func' is an odd number or not. Mask and control-
|
| 194 | * fields of odd number 'func' is located at upper portion of
|
| 195 | * a register. Extra shift is needed.
|
| 196 |
|
| 197 | if (func & BIT(0))
|
| 198 | reg <<= SPPCTL_FULLY_PINMUX_UPPER_SHIFT;
|
| 199 |
|
| 200 |
|
| 201 | offset = func * 2;
|
| 202 | offset &= GENMASK(31, 2);
|
| 203 |
|
| 204 | writel(reg, pctl->moon2_base + offset);
|
| 205 | }
|
| 206 |
|
| 207 | |
| 208 | * sppctl_gmx_set() - Set pin of group-pinmux.
|
| 209 | *
|
| 210 | * Mask-fields and control-fields of group-pinmux function of SP7021 are
|
| 211 | * arranged as shown below:
|
| 212 | *
|
| 213 | * register | mask-fields | control-fields
|
| 214 | * ----------+--------------+----------------
|
| 215 | * base[0] | (31 : 16) | (15 : 0)
|
| 216 | * base[1] | (31 : 24) | (15 : 0)
|
| 217 | * base[2] | (31 : 24) | (15 : 0)
|
| 218 | * : | : | :
|
| 219 | *
|
| 220 | * where mask-fields are used to protect control-fields from write-in
|
| 221 | * accidentally. Set the corresponding bits in the mask-field before
|
| 222 | * you write a value into a control-field.
|
| 223 | *
|
| 224 | * Control-fields are used to set where the function pin is going to
|
| 225 | * be routed to. A control-field consists of one or more bits.
|
| 226 |
|
| 227 | static void sppctl_gmx_set(struct sppctl_pdata *pctl, u8 reg_off, u8 bit_off, u8 bit_sz,
|
| 228 | u8 val)
|
| 229 | {
|
| 230 | u32 mask, reg;
|
| 231 |
|
| 232 | |
| 233 | * Note that upper 16-bit word are mask-fields and lower 16-bit
|
| 234 | * word are the control-fields. Set corresponding bits in mask-
|
| 235 | * field before write to a control-field.
|
| 236 |
|
| 237 | mask = GENMASK(bit_sz - 1, 0) << SPPCTL_MOON_REG_MASK_SHIFT;
|
| 238 | reg = (mask | val) << bit_off;
|
| 239 |
|
| 240 | writel(reg, pctl->moon1_base + reg_off * 4);
|
| 241 | }
|
| 242 |
|
| 243 | |
| 244 | * sppctl_first_get() - get bit of FIRST register.
|
| 245 | *
|
| 246 | * There are 4 FIRST registers. Each has 32 control-bits.
|
| 247 | * Totally, there are 4 * 32 = 128 control-bits.
|
| 248 | * Control-bits are arranged as shown below:
|
| 249 | *
|
| 250 | * registers | control-bits
|
| 251 | * -----------+--------------
|
| 252 | * first[0] | (31 : 0)
|
| 253 | * first[1] | (63 : 32)
|
| 254 | * first[2] | (95 : 64)
|
| 255 | * first[3] | (127 : 96)
|
| 256 | *
|
| 257 | * Each control-bit sets type of a GPIO pin.
|
| 258 | * 0: a fully-pinmux pin
|
| 259 | * 1: a GPIO or IOP pin
|
| 260 |
|
| 261 | static int sppctl_first_get(struct gpio_chip *chip, unsigned int offset)
|
| 262 | {
|
| 263 | struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip);
|
| 264 | u32 reg_off, bit_off, reg;
|
| 265 |
|
| 266 | bit_off = sppctl_get_reg_and_bit_offset(offset, ®_off);
|
| 267 | reg = sppctl_first_readl(spp_gchip, reg_off);
|
| 268 |
|
| 269 | return (reg & BIT(bit_off)) ? 1 : 0;
|
| 270 | }
|
| 271 |
|
| 272 | |
| 273 | * sppctl_master_get() - get bit of MASTER register.
|
| 274 | *
|
| 275 | * There are 8 MASTER registers. Each has 16 mask-bits and 16 control-bits.
|
| 276 | * Upper 16-bit of MASTER registers are mask-bits while lower 16-bit are
|
| 277 | * control-bits. Totally, there are 128 mask-bits and 128 control-bits.
|
| 278 | * They are arranged as shown below:
|
| 279 | *
|
| 280 | * register | mask-bits | control-bits
|
| 281 | * -----------+-------------+--------------
|
| 282 | * master[0] | (15 : 0) | (15 : 0)
|
| 283 | * master[1] | (31 : 16) | (31 : 16)
|
| 284 | * master[2] | (47 : 32) | (47 : 32)
|
| 285 | * : | : | :
|
| 286 | * master[7] | (127 : 112) | (127 : 112)
|
| 287 | *
|
| 288 | * where mask-bits are used to protect control-bits from write-in
|
| 289 | * accidentally. Set the corresponding mask-bit before you write
|
| 290 | * a value into a control-bit.
|
| 291 | *
|
| 292 | * Each control-bit sets type of a GPIO pin when FIRST bit is 1.
|
| 293 | * 0: a IOP pin
|
| 294 | * 1: a GPIO pin
|
| 295 |
|
| 296 | static int sppctl_master_get(struct gpio_chip *chip, unsigned int offset)
|
| 297 | {
|
| 298 | struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip);
|
| 299 | u32 reg_off, bit_off, reg;
|
| 300 |
|
| 301 | bit_off = sppctl_get_moon_reg_and_bit_offset(offset, ®_off);
|
| 302 | reg = sppctl_gpio_master_readl(spp_gchip, reg_off);
|
| 303 | return (reg & BIT(bit_off)) ? 1 : 0;
|
| 304 | }
|
| 305 |
|
| 306 | static void sppctl_first_master_set(struct gpio_chip *chip, unsigned int offset,
|
| 307 | enum mux_first_reg first, enum mux_master_reg master)
|
| 308 | {
|
| 309 | struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip);
|
| 310 | u32 reg_off, bit_off, reg;
|
| 311 | enum mux_first_reg val;
|
| 312 |
|
| 313 |
|
| 314 | if (first != mux_f_keep) {
|
| 315 | bit_off = sppctl_get_reg_and_bit_offset(offset, ®_off);
|
| 316 | reg = sppctl_first_readl(spp_gchip, reg_off);
|
| 317 | val = (reg & BIT(bit_off)) ? mux_f_gpio : mux_f_mux;
|
| 318 |
|
| 319 | if (first != val)
|
| 320 | switch (first) {
|
| 321 | case mux_f_gpio:
|
| 322 | reg |= BIT(bit_off);
|
| 323 | sppctl_first_writel(spp_gchip, reg, reg_off);
|
| 324 | break;
|
| 325 |
|
| 326 | case mux_f_mux:
|
| 327 | reg &= ~BIT(bit_off);
|
| 328 | sppctl_first_writel(spp_gchip, reg, reg_off);
|
| 329 | break;
|
| 330 |
|
| 331 | case mux_f_keep:
|
| 332 | break;
|
| 333 | }
|
| 334 | }
|
| 335 |
|
| 336 |
|
| 337 | if (master != mux_m_keep) {
|
| 338 | reg = sppctl_prep_moon_reg_and_offset(offset, ®_off, (master == mux_m_gpio));
|
| 339 | sppctl_gpio_master_writel(spp_gchip, reg, reg_off);
|
| 340 | }
|
| 341 | }
|
| 342 |
|
| 343 | static void sppctl_gpio_input_inv_set(struct gpio_chip *chip, unsigned int offset)
|
| 344 | {
|
| 345 | struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip);
|
| 346 | u32 reg_off, reg;
|
| 347 |
|
| 348 | reg = sppctl_prep_moon_reg_and_offset(offset, ®_off, 1);
|
| 349 | sppctl_gpio_iinv_writel(spp_gchip, reg, reg_off);
|
| 350 | }
|
| 351 |
|
| 352 | static void sppctl_gpio_output_inv_set(struct gpio_chip *chip, unsigned int offset)
|
| 353 | {
|
| 354 | struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip);
|
| 355 | u32 reg_off, reg;
|
| 356 |
|
| 357 | reg = sppctl_prep_moon_reg_and_offset(offset, ®_off, 1);
|
| 358 | sppctl_gpio_oinv_writel(spp_gchip, reg, reg_off);
|
| 359 | }
|
| 360 |
|
| 361 | static int sppctl_gpio_output_od_get(struct gpio_chip *chip, unsigned int offset)
|
| 362 | {
|
| 363 | struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip);
|
| 364 | u32 reg_off, bit_off, reg;
|
| 365 |
|
| 366 | bit_off = sppctl_get_moon_reg_and_bit_offset(offset, ®_off);
|
| 367 | reg = sppctl_gpio_od_readl(spp_gchip, reg_off);
|
| 368 |
|
| 369 | return (reg & BIT(bit_off)) ? 1 : 0;
|
| 370 | }
|
| 371 |
|
| 372 | static void sppctl_gpio_output_od_set(struct gpio_chip *chip, unsigned int offset,
|
| 373 | unsigned int val)
|
| 374 | {
|
| 375 | struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip);
|
| 376 | u32 reg_off, reg;
|
| 377 |
|
| 378 | reg = sppctl_prep_moon_reg_and_offset(offset, ®_off, val);
|
| 379 | sppctl_gpio_od_writel(spp_gchip, reg, reg_off);
|
| 380 | }
|
| 381 |
|
| 382 | static int sppctl_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
|
| 383 | {
|
| 384 | struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip);
|
| 385 | u32 reg_off, bit_off, reg;
|
| 386 |
|
| 387 | bit_off = sppctl_get_moon_reg_and_bit_offset(offset, ®_off);
|
| 388 | reg = sppctl_gpio_oe_readl(spp_gchip, reg_off);
|
| 389 |
|
| 390 | return (reg & BIT(bit_off)) ? 0 : 1;
|
| 391 | }
|
| 392 |
|
| 393 | static int sppctl_gpio_inv_get(struct gpio_chip *chip, unsigned int offset)
|
| 394 | {
|
| 395 | struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip);
|
| 396 | u32 reg_off, bit_off, reg;
|
| 397 | unsigned long flags;
|
| 398 |
|
| 399 | bit_off = sppctl_get_moon_reg_and_bit_offset(offset, ®_off);
|
| 400 |
|
| 401 | spin_lock_irqsave(&spp_gchip->lock, flags);
|
| 402 |
|
| 403 | if (sppctl_gpio_get_direction(chip, offset))
|
| 404 | reg = sppctl_gpio_iinv_readl(spp_gchip, reg_off);
|
| 405 | else
|
| 406 | reg = sppctl_gpio_oinv_readl(spp_gchip, reg_off);
|
| 407 |
|
| 408 | spin_unlock_irqrestore(&spp_gchip->lock, flags);
|
| 409 |
|
| 410 | return (reg & BIT(bit_off)) ? 1 : 0;
|
| 411 | }
|
| 412 |
|
| 413 | static int sppctl_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
|
| 414 | {
|
| 415 | struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip);
|
| 416 | unsigned long flags;
|
| 417 | u32 reg_off, reg;
|
| 418 |
|
| 419 | reg = sppctl_prep_moon_reg_and_offset(offset, ®_off, 0);
|
| 420 |
|
| 421 | spin_lock_irqsave(&spp_gchip->lock, flags);
|
| 422 |
|
| 423 | sppctl_gpio_oe_writel(spp_gchip, reg, reg_off);
|
| 424 |
|
| 425 | spin_unlock_irqrestore(&spp_gchip->lock, flags);
|
| 426 | return 0;
|
| 427 | }
|
| 428 |
|
| 429 | static int sppctl_gpio_direction_output(struct gpio_chip *chip, unsigned int offset, int val)
|
| 430 | {
|
| 431 | struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip);
|
| 432 | unsigned long flags;
|
| 433 | u32 reg_off, reg;
|
| 434 |
|
| 435 | reg = sppctl_prep_moon_reg_and_offset(offset, ®_off, 1);
|
| 436 |
|
| 437 | spin_lock_irqsave(&spp_gchip->lock, flags);
|
| 438 |
|
| 439 | sppctl_gpio_oe_writel(spp_gchip, reg, reg_off);
|
| 440 |
|
| 441 | if (val < 0) {
|
| 442 | spin_unlock_irqrestore(&spp_gchip->lock, flags);
|
| 443 | return 0;
|
| 444 | }
|
| 445 |
|
| 446 | reg = sppctl_prep_moon_reg_and_offset(offset, ®_off, val);
|
| 447 | sppctl_gpio_out_writel(spp_gchip, reg, reg_off);
|
| 448 |
|
| 449 | spin_unlock_irqrestore(&spp_gchip->lock, flags);
|
| 450 | return 0;
|
| 451 | }
|
| 452 |
|
| 453 | static int sppctl_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
| 454 | {
|
| 455 | struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip);
|
| 456 | u32 reg_off, bit_off, reg;
|
| 457 |
|
| 458 | bit_off = sppctl_get_reg_and_bit_offset(offset, ®_off);
|
| 459 | reg = sppctl_gpio_in_readl(spp_gchip, reg_off);
|
| 460 |
|
| 461 | return (reg & BIT(bit_off)) ? 1 : 0;
|
| 462 | }
|
| 463 |
|
| 464 | static int sppctl_gpio_set(struct gpio_chip *chip, unsigned int offset, int val)
|
| 465 | {
|
| 466 | struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip);
|
| 467 | u32 reg_off, reg;
|
| 468 |
|
| 469 | reg = sppctl_prep_moon_reg_and_offset(offset, ®_off, val);
|
| 470 | sppctl_gpio_out_writel(spp_gchip, reg, reg_off);
|
| 471 |
|
| 472 | return 0;
|
| 473 | }
|
| 474 |
|
| 475 | static int sppctl_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
|
| 476 | unsigned long config)
|
| 477 | {
|
| 478 | enum pin_config_param param = pinconf_to_config_param(config);
|
| 479 | struct sppctl_gpio_chip *spp_gchip = gpiochip_get_data(chip);
|
| 480 | u32 reg_off, reg;
|
| 481 |
|
| 482 | switch (param) {
|
| 483 | case PIN_CONFIG_DRIVE_OPEN_DRAIN:
|
| 484 | reg = sppctl_prep_moon_reg_and_offset(offset, ®_off, 1);
|
| 485 | sppctl_gpio_od_writel(spp_gchip, reg, reg_off);
|
| 486 | break;
|
| 487 |
|
| 488 | case PIN_CONFIG_INPUT_ENABLE:
|
| 489 | break;
|
| 490 |
|
| 491 | case PIN_CONFIG_LEVEL:
|
| 492 | return sppctl_gpio_direction_output(chip, offset, 0);
|
| 493 |
|
| 494 | case PIN_CONFIG_PERSIST_STATE:
|
| 495 | return -ENOTSUPP;
|
| 496 |
|
| 497 | default:
|
| 498 | return -EINVAL;
|
| 499 | }
|
| 500 |
|
| 501 | return 0;
|
| 502 | }
|
| 503 |
|
| 504 | static void sppctl_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
| 505 | {
|
| 506 | int i;
|
| 507 |
|
| 508 | for (i = 0; i < chip->ngpio; i++) {
|
| 509 | char *label __free(kfree) = gpiochip_dup_line_label(chip, i);
|
| 510 | if (IS_ERR(label))
|
| 511 | continue;
|
| 512 |
|
| 513 | seq_printf(s, " gpio-%03d (%-16.16s | %-16.16s)", i + chip->base,
|
| 514 | chip->names[i], label ?: "");
|
| 515 | seq_printf(s, " %c", sppctl_gpio_get_direction(chip, i) ? 'I' : 'O');
|
| 516 | seq_printf(s, ":%d", sppctl_gpio_get(chip, i));
|
| 517 | seq_printf(s, " %s", sppctl_first_get(chip, i) ? "gpi" : "mux");
|
| 518 | seq_printf(s, " %s", sppctl_master_get(chip, i) ? "gpi" : "iop");
|
| 519 | seq_printf(s, " %s", sppctl_gpio_inv_get(chip, i) ? "inv" : " ");
|
| 520 | seq_printf(s, " %s", sppctl_gpio_output_od_get(chip, i) ? "oDr" : "");
|
| 521 | seq_puts(s, "\n");
|
| 522 | }
|
| 523 | }
|
| 524 |
|
| 525 | static int sppctl_gpio_new(struct platform_device *pdev, struct sppctl_pdata *pctl)
|
| 526 | {
|
| 527 | struct sppctl_gpio_chip *spp_gchip;
|
| 528 | struct gpio_chip *gchip;
|
| 529 | int err;
|
| 530 |
|
| 531 | spp_gchip = devm_kzalloc(&pdev->dev, sizeof(*spp_gchip), GFP_KERNEL);
|
| 532 | if (!spp_gchip)
|
| 533 | return -ENOMEM;
|
| 534 | pctl->spp_gchip = spp_gchip;
|
| 535 |
|
| 536 | spp_gchip->gpioxt_base = pctl->gpioxt_base;
|
| 537 | spp_gchip->first_base = pctl->first_base;
|
| 538 | spin_lock_init(&spp_gchip->lock);
|
| 539 |
|
| 540 | gchip = &spp_gchip->chip;
|
| 541 | gchip->label = SPPCTL_MODULE_NAME;
|
| 542 | gchip->parent = &pdev->dev;
|
| 543 | gchip->owner = THIS_MODULE;
|
| 544 | gchip->request = gpiochip_generic_request;
|
| 545 | gchip->free = gpiochip_generic_free;
|
| 546 | gchip->get_direction = sppctl_gpio_get_direction;
|
| 547 | gchip->direction_input = sppctl_gpio_direction_input;
|
| 548 | gchip->direction_output = sppctl_gpio_direction_output;
|
| 549 | gchip->get = sppctl_gpio_get;
|
| 550 | gchip->set = sppctl_gpio_set;
|
| 551 | gchip->set_config = sppctl_gpio_set_config;
|
| 552 | gchip->dbg_show = IS_ENABLED(CONFIG_DEBUG_FS) ?
|
| 553 | sppctl_gpio_dbg_show : NULL;
|
| 554 | gchip->base = -1;
|
| 555 | gchip->ngpio = sppctl_gpio_list_sz;
|
| 556 | gchip->names = sppctl_gpio_list_s;
|
| 557 |
|
| 558 | pctl->pctl_grange.npins = gchip->ngpio;
|
| 559 | pctl->pctl_grange.name = gchip->label;
|
| 560 | pctl->pctl_grange.gc = gchip;
|
| 561 |
|
| 562 | err = devm_gpiochip_add_data(&pdev->dev, gchip, spp_gchip);
|
| 563 | if (err)
|
| 564 | return dev_err_probe(&pdev->dev, err, "Failed to add gpiochip!\n");
|
| 565 |
|
| 566 | return 0;
|
| 567 | }
|
| 568 |
|
| 569 | static int sppctl_pin_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
|
| 570 | unsigned long *config)
|
| 571 | {
|
| 572 | struct sppctl_pdata *pctl = pinctrl_dev_get_drvdata(pctldev);
|
| 573 | unsigned int param = pinconf_to_config_param(*config);
|
| 574 | unsigned int arg;
|
| 575 |
|
| 576 | switch (param) {
|
| 577 | case PIN_CONFIG_DRIVE_OPEN_DRAIN:
|
| 578 | if (!sppctl_gpio_output_od_get(&pctl->spp_gchip->chip, pin))
|
| 579 | return -EINVAL;
|
| 580 | arg = 0;
|
| 581 | break;
|
| 582 |
|
| 583 | case PIN_CONFIG_LEVEL:
|
| 584 | if (!sppctl_first_get(&pctl->spp_gchip->chip, pin))
|
| 585 | return -EINVAL;
|
| 586 | if (!sppctl_master_get(&pctl->spp_gchip->chip, pin))
|
| 587 | return -EINVAL;
|
| 588 | if (sppctl_gpio_get_direction(&pctl->spp_gchip->chip, pin))
|
| 589 | return -EINVAL;
|
| 590 | arg = sppctl_gpio_get(&pctl->spp_gchip->chip, pin);
|
| 591 | break;
|
| 592 |
|
| 593 | default:
|
| 594 | return -EOPNOTSUPP;
|
| 595 | }
|
| 596 | *config = pinconf_to_config_packed(param, arg);
|
| 597 |
|
| 598 | return 0;
|
| 599 | }
|
| 600 |
|
| 601 | static int sppctl_pin_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
|
| 602 | unsigned long *configs, unsigned int num_configs)
|
| 603 | {
|
| 604 | struct sppctl_pdata *pctl = pinctrl_dev_get_drvdata(pctldev);
|
| 605 | int i;
|
| 606 |
|
| 607 |
|
| 608 | if (configs[0] == SPPCTL_IOP_CONFIGS) {
|
| 609 | sppctl_first_master_set(&pctl->spp_gchip->chip, pin, mux_f_gpio, mux_m_iop);
|
| 610 | return 0;
|
| 611 | }
|
| 612 |
|
| 613 | for (i = 0; i < num_configs; i++) {
|
| 614 | if (configs[i] & SPPCTL_PCTL_L_OUT)
|
| 615 | sppctl_gpio_direction_output(&pctl->spp_gchip->chip, pin, 0);
|
| 616 | if (configs[i] & SPPCTL_PCTL_L_OU1)
|
| 617 | sppctl_gpio_direction_output(&pctl->spp_gchip->chip, pin, 1);
|
| 618 | if (configs[i] & SPPCTL_PCTL_L_INV)
|
| 619 | sppctl_gpio_input_inv_set(&pctl->spp_gchip->chip, pin);
|
| 620 | if (configs[i] & SPPCTL_PCTL_L_ONV)
|
| 621 | sppctl_gpio_output_inv_set(&pctl->spp_gchip->chip, pin);
|
| 622 | if (configs[i] & SPPCTL_PCTL_L_ODR)
|
| 623 | sppctl_gpio_output_od_set(&pctl->spp_gchip->chip, pin, 1);
|
| 624 | }
|
| 625 |
|
| 626 | return 0;
|
| 627 | }
|
| 628 |
|
| 629 | static const struct pinconf_ops sppctl_pconf_ops = {
|
| 630 | .is_generic = true,
|
| 631 | .pin_config_get = sppctl_pin_config_get,
|
| 632 | .pin_config_set = sppctl_pin_config_set,
|
| 633 | };
|
| 634 |
|
| 635 | static int sppctl_get_functions_count(struct pinctrl_dev *pctldev)
|
| 636 | {
|
| 637 | return sppctl_list_funcs_sz;
|
| 638 | }
|
| 639 |
|
| 640 | static const char *sppctl_get_function_name(struct pinctrl_dev *pctldev,
|
| 641 | unsigned int selector)
|
| 642 | {
|
| 643 | return sppctl_list_funcs[selector].name;
|
| 644 | }
|
| 645 |
|
| 646 | static int sppctl_get_function_groups(struct pinctrl_dev *pctldev, unsigned int selector,
|
| 647 | const char * const **groups, unsigned int *num_groups)
|
| 648 | {
|
| 649 | struct sppctl_pdata *pctl = pinctrl_dev_get_drvdata(pctldev);
|
| 650 | const struct sppctl_func *f = &sppctl_list_funcs[selector];
|
| 651 | int i;
|
| 652 |
|
| 653 | *num_groups = 0;
|
| 654 | switch (f->type) {
|
| 655 | case pinmux_type_fpmx:
|
| 656 | *num_groups = sppctl_pmux_list_sz;
|
| 657 | *groups = sppctl_pmux_list_s;
|
| 658 | break;
|
| 659 |
|
| 660 | case pinmux_type_grp:
|
| 661 | if (!f->grps)
|
| 662 | break;
|
| 663 |
|
| 664 | *num_groups = f->gnum;
|
| 665 | for (i = 0; i < pctl->unq_grps_sz; i++)
|
| 666 | if (pctl->g2fp_maps[i].f_idx == selector)
|
| 667 | break;
|
| 668 | *groups = &pctl->unq_grps[i];
|
| 669 | break;
|
| 670 |
|
| 671 | default:
|
| 672 | dev_err(pctldev->dev, "Unknown pinmux (selector: %d, type: %d)\n",
|
| 673 | selector, f->type);
|
| 674 | break;
|
| 675 | }
|
| 676 |
|
| 677 | return 0;
|
| 678 | }
|
| 679 |
|
| 680 | |
| 681 | * sppctl_fully_pinmux_conv - Convert GPIO# to fully-pinmux control-field setting
|
| 682 | *
|
| 683 | * Each fully-pinmux function can be mapped to any of GPIO 8 ~ 71 by
|
| 684 | * settings its control-field. Refer to following table:
|
| 685 | *
|
| 686 | * control-field | GPIO
|
| 687 | * --------------+--------
|
| 688 | * 0 | No map
|
| 689 | * 1 | 8
|
| 690 | * 2 | 9
|
| 691 | * 3 | 10
|
| 692 | * : | :
|
| 693 | * 65 | 71
|
| 694 |
|
| 695 | static inline int sppctl_fully_pinmux_conv(unsigned int offset)
|
| 696 | {
|
| 697 | return (offset < 8) ? 0 : offset - 7;
|
| 698 | }
|
| 699 |
|
| 700 | static int sppctl_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector,
|
| 701 | unsigned int group_selector)
|
| 702 | {
|
| 703 | const struct sppctl_func *f = &sppctl_list_funcs[func_selector];
|
| 704 | struct sppctl_pdata *pctl = pinctrl_dev_get_drvdata(pctldev);
|
| 705 | struct grp2fp_map g2fpm = pctl->g2fp_maps[group_selector];
|
| 706 | int i;
|
| 707 |
|
| 708 | switch (f->type) {
|
| 709 | case pinmux_type_fpmx:
|
| 710 | sppctl_first_master_set(&pctl->spp_gchip->chip, group_selector,
|
| 711 | mux_f_mux, mux_m_keep);
|
| 712 | sppctl_func_set(pctl, func_selector, sppctl_fully_pinmux_conv(group_selector));
|
| 713 | break;
|
| 714 |
|
| 715 | case pinmux_type_grp:
|
| 716 | for (i = 0; i < f->grps[g2fpm.g_idx].pnum; i++)
|
| 717 | sppctl_first_master_set(&pctl->spp_gchip->chip,
|
| 718 | f->grps[g2fpm.g_idx].pins[i],
|
| 719 | mux_f_mux, mux_m_keep);
|
| 720 | sppctl_gmx_set(pctl, f->roff, f->boff, f->blen, f->grps[g2fpm.g_idx].gval);
|
| 721 | break;
|
| 722 |
|
| 723 | default:
|
| 724 | dev_err(pctldev->dev, "Unknown pinmux type (func_selector: %d, type: %d)\n",
|
| 725 | func_selector, f->type);
|
| 726 | break;
|
| 727 | }
|
| 728 |
|
| 729 | return 0;
|
| 730 | }
|
| 731 |
|
| 732 | static int sppctl_gpio_request_enable(struct pinctrl_dev *pctldev,
|
| 733 | struct pinctrl_gpio_range *range, unsigned int offset)
|
| 734 | {
|
| 735 | struct sppctl_pdata *pctl = pinctrl_dev_get_drvdata(pctldev);
|
| 736 | int g_f, g_m;
|
| 737 |
|
| 738 | g_f = sppctl_first_get(&pctl->spp_gchip->chip, offset);
|
| 739 | g_m = sppctl_master_get(&pctl->spp_gchip->chip, offset);
|
| 740 | if (g_f == mux_f_gpio && g_m == mux_m_gpio)
|
| 741 | return 0;
|
| 742 |
|
| 743 | sppctl_first_master_set(&pctl->spp_gchip->chip, offset, mux_f_gpio, mux_m_gpio);
|
| 744 | return 0;
|
| 745 | }
|
| 746 |
|
| 747 | static const struct pinmux_ops sppctl_pinmux_ops = {
|
| 748 | .get_functions_count = sppctl_get_functions_count,
|
| 749 | .get_function_name = sppctl_get_function_name,
|
| 750 | .get_function_groups = sppctl_get_function_groups,
|
| 751 | .set_mux = sppctl_set_mux,
|
| 752 | .gpio_request_enable = sppctl_gpio_request_enable,
|
| 753 | .strict = true,
|
| 754 | };
|
| 755 |
|
| 756 | static int sppctl_get_groups_count(struct pinctrl_dev *pctldev)
|
| 757 | {
|
| 758 | struct sppctl_pdata *pctl = pinctrl_dev_get_drvdata(pctldev);
|
| 759 |
|
| 760 | return pctl->unq_grps_sz;
|
| 761 | }
|
| 762 |
|
| 763 | static const char *sppctl_get_group_name(struct pinctrl_dev *pctldev, unsigned int selector)
|
| 764 | {
|
| 765 | struct sppctl_pdata *pctl = pinctrl_dev_get_drvdata(pctldev);
|
| 766 |
|
| 767 | return pctl->unq_grps[selector];
|
| 768 | }
|
| 769 |
|
| 770 | static int sppctl_get_group_pins(struct pinctrl_dev *pctldev, unsigned int selector,
|
| 771 | const unsigned int **pins, unsigned int *num_pins)
|
| 772 | {
|
| 773 | struct sppctl_pdata *pctl = pinctrl_dev_get_drvdata(pctldev);
|
| 774 | struct grp2fp_map g2fpm = pctl->g2fp_maps[selector];
|
| 775 | const struct sppctl_func *f;
|
| 776 |
|
| 777 | f = &sppctl_list_funcs[g2fpm.f_idx];
|
| 778 | *num_pins = 0;
|
| 779 |
|
| 780 |
|
| 781 | if (f->type != pinmux_type_grp) {
|
| 782 | *num_pins = 1;
|
| 783 | *pins = &sppctl_pins_gpio[selector];
|
| 784 | return 0;
|
| 785 | }
|
| 786 |
|
| 787 |
|
| 788 | if (!f->grps)
|
| 789 | return 0;
|
| 790 |
|
| 791 | if (f->gnum < 1)
|
| 792 | return 0;
|
| 793 |
|
| 794 | *num_pins = f->grps[g2fpm.g_idx].pnum;
|
| 795 | *pins = f->grps[g2fpm.g_idx].pins;
|
| 796 |
|
| 797 | return 0;
|
| 798 | }
|
| 799 |
|
| 800 | #ifdef CONFIG_DEBUG_FS
|
| 801 | static void sppctl_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
|
| 802 | unsigned int offset)
|
| 803 | {
|
| 804 | struct sppctl_pdata *pctl = pinctrl_dev_get_drvdata(pctldev);
|
| 805 | const char *pin_type;
|
| 806 | u8 first, master;
|
| 807 |
|
| 808 | first = sppctl_first_get(&pctl->spp_gchip->chip, offset);
|
| 809 | master = sppctl_master_get(&pctl->spp_gchip->chip, offset);
|
| 810 | if (first)
|
| 811 | if (master)
|
| 812 | pin_type = "GPIO";
|
| 813 | else
|
| 814 | pin_type = " IOP";
|
| 815 | else
|
| 816 | pin_type = " MUX";
|
| 817 | seq_printf(s, " %s", pin_type);
|
| 818 | }
|
| 819 | #endif
|
| 820 |
|
| 821 | static int sppctl_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node *np_config,
|
| 822 | struct pinctrl_map **map, unsigned int *num_maps)
|
| 823 | {
|
| 824 | struct sppctl_pdata *pctl = pinctrl_dev_get_drvdata(pctldev);
|
| 825 | int nmG = of_property_count_strings(np_config, "groups");
|
| 826 | const struct sppctl_func *f = NULL;
|
| 827 | u8 pin_num, pin_type, pin_func;
|
| 828 | struct device_node *parent;
|
| 829 | unsigned long *configs;
|
| 830 | struct property *prop;
|
| 831 | const char *s_f, *s_g;
|
| 832 |
|
| 833 | const __be32 *list;
|
| 834 | u32 dt_pin, dt_fun;
|
| 835 | int i, size = 0;
|
| 836 |
|
| 837 | list = of_get_property(np_config, "sunplus,pins", &size);
|
| 838 | *num_maps = size / sizeof(*list);
|
| 839 |
|
| 840 | |
| 841 | * Process property:
|
| 842 | * sunplus,pins = < u32 u32 u32 ... >;
|
| 843 | *
|
| 844 | * Each 32-bit integer defines a individual pin in which:
|
| 845 | *
|
| 846 | * Bit 32~24: defines GPIO pin number. Its range is 0 ~ 98.
|
| 847 | * Bit 23~16: defines types: (1) fully-pinmux pins
|
| 848 | * (2) IO processor pins
|
| 849 | * (3) digital GPIO pins
|
| 850 | * Bit 15~8: defines pins of peripherals (which are defined in
|
| 851 | * 'include/dt-binging/pinctrl/sppctl.h').
|
| 852 | * Bit 7~0: defines types or initial-state of digital GPIO pins.
|
| 853 |
|
| 854 | for (i = 0; i < (*num_maps); i++) {
|
| 855 | dt_pin = be32_to_cpu(list[i]);
|
| 856 | pin_num = FIELD_GET(GENMASK(31, 24), dt_pin);
|
| 857 |
|
| 858 | if (pin_num >= sppctl_pins_all_sz) {
|
| 859 | dev_err(pctldev->dev, "Invalid pin property at index %d (0x%08x)\n",
|
| 860 | i, dt_pin);
|
| 861 | return -EINVAL;
|
| 862 | }
|
| 863 | }
|
| 864 |
|
| 865 | if (nmG <= 0)
|
| 866 | nmG = 0;
|
| 867 |
|
| 868 | *map = kzalloc_objs(**map, *num_maps + nmG);
|
| 869 | if (!(*map))
|
| 870 | return -ENOMEM;
|
| 871 |
|
| 872 | parent = of_get_parent(np_config);
|
| 873 | for (i = 0; i < (*num_maps); i++) {
|
| 874 | dt_pin = be32_to_cpu(list[i]);
|
| 875 | pin_num = FIELD_GET(GENMASK(31, 24), dt_pin);
|
| 876 | pin_type = FIELD_GET(GENMASK(23, 16), dt_pin);
|
| 877 | pin_func = FIELD_GET(GENMASK(15, 8), dt_pin);
|
| 878 | (*map)[i].name = parent->name;
|
| 879 |
|
| 880 | if (pin_type == SPPCTL_PCTL_G_GPIO) {
|
| 881 |
|
| 882 | (*map)[i].type = PIN_MAP_TYPE_CONFIGS_PIN;
|
| 883 | (*map)[i].data.configs.num_configs = 1;
|
| 884 | (*map)[i].data.configs.group_or_pin = pin_get_name(pctldev, pin_num);
|
| 885 | configs = kmalloc_obj(*configs);
|
| 886 | if (!configs)
|
| 887 | goto sppctl_map_err;
|
| 888 | *configs = FIELD_GET(GENMASK(7, 0), dt_pin);
|
| 889 | (*map)[i].data.configs.configs = configs;
|
| 890 |
|
| 891 | dev_dbg(pctldev->dev, "%s: GPIO (%s)\n",
|
| 892 | (*map)[i].data.configs.group_or_pin,
|
| 893 | (*configs & (SPPCTL_PCTL_L_OUT | SPPCTL_PCTL_L_OU1)) ?
|
| 894 | "OUT" : "IN");
|
| 895 | } else if (pin_type == SPPCTL_PCTL_G_IOPP) {
|
| 896 |
|
| 897 | (*map)[i].type = PIN_MAP_TYPE_CONFIGS_PIN;
|
| 898 | (*map)[i].data.configs.num_configs = 1;
|
| 899 | (*map)[i].data.configs.group_or_pin = pin_get_name(pctldev, pin_num);
|
| 900 | configs = kmalloc_obj(*configs);
|
| 901 | if (!configs)
|
| 902 | goto sppctl_map_err;
|
| 903 | *configs = SPPCTL_IOP_CONFIGS;
|
| 904 | (*map)[i].data.configs.configs = configs;
|
| 905 |
|
| 906 | dev_dbg(pctldev->dev, "%s: IOP\n",
|
| 907 | (*map)[i].data.configs.group_or_pin);
|
| 908 | } else {
|
| 909 |
|
| 910 | (*map)[i].type = PIN_MAP_TYPE_MUX_GROUP;
|
| 911 | (*map)[i].data.mux.function = sppctl_list_funcs[pin_func].name;
|
| 912 | (*map)[i].data.mux.group = pin_get_name(pctldev, pin_num);
|
| 913 |
|
| 914 | dev_dbg(pctldev->dev, "%s: %s\n", (*map)[i].data.mux.group,
|
| 915 | (*map)[i].data.mux.function);
|
| 916 | }
|
| 917 | }
|
| 918 |
|
| 919 | |
| 920 | * Process properties:
|
| 921 | * function = "xxx";
|
| 922 | * groups = "yyy";
|
| 923 |
|
| 924 | if (nmG > 0 && of_property_read_string(np_config, "function", &s_f) == 0) {
|
| 925 | of_property_for_each_string(np_config, "groups", prop, s_g) {
|
| 926 | (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP;
|
| 927 | (*map)[*num_maps].data.mux.function = s_f;
|
| 928 | (*map)[*num_maps].data.mux.group = s_g;
|
| 929 | (*num_maps)++;
|
| 930 |
|
| 931 | dev_dbg(pctldev->dev, "%s: %s\n", s_f, s_g);
|
| 932 | }
|
| 933 | }
|
| 934 |
|
| 935 | |
| 936 | * Process property:
|
| 937 | * sunplus,zerofunc = < u32 u32 u32 ...>
|
| 938 |
|
| 939 | list = of_get_property(np_config, "sunplus,zerofunc", &size);
|
| 940 | if (list) {
|
| 941 | for (i = 0; i < (size / sizeof(*list)); i++) {
|
| 942 | dt_fun = be32_to_cpu(list[i]);
|
| 943 | if (dt_fun >= sppctl_list_funcs_sz) {
|
| 944 | dev_err(pctldev->dev, "Zero-func %d out of range!\n",
|
| 945 | dt_fun);
|
| 946 | continue;
|
| 947 | }
|
| 948 |
|
| 949 | f = &sppctl_list_funcs[dt_fun];
|
| 950 | switch (f->type) {
|
| 951 | case pinmux_type_fpmx:
|
| 952 | sppctl_func_set(pctl, dt_fun, 0);
|
| 953 | dev_dbg(pctldev->dev, "%s: No map\n", f->name);
|
| 954 | break;
|
| 955 |
|
| 956 | case pinmux_type_grp:
|
| 957 | sppctl_gmx_set(pctl, f->roff, f->boff, f->blen, 0);
|
| 958 | dev_dbg(pctldev->dev, "%s: No map\n", f->name);
|
| 959 | break;
|
| 960 |
|
| 961 | default:
|
| 962 | dev_err(pctldev->dev, "Wrong zero-group: %d (%s)\n",
|
| 963 | dt_fun, f->name);
|
| 964 | break;
|
| 965 | }
|
| 966 | }
|
| 967 | }
|
| 968 |
|
| 969 | of_node_put(parent);
|
| 970 | dev_dbg(pctldev->dev, "%d pins mapped\n", *num_maps);
|
| 971 | return 0;
|
| 972 |
|
| 973 | sppctl_map_err:
|
| 974 | for (i = 0; i < (*num_maps); i++)
|
| 975 | if ((*map)[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
|
| 976 | kfree((*map)[i].data.configs.configs);
|
| 977 | kfree(*map);
|
| 978 | of_node_put(parent);
|
| 979 | return -ENOMEM;
|
| 980 | }
|
| 981 |
|
| 982 | static const struct pinctrl_ops sppctl_pctl_ops = {
|
| 983 | .get_groups_count = sppctl_get_groups_count,
|
| 984 | .get_group_name = sppctl_get_group_name,
|
| 985 | .get_group_pins = sppctl_get_group_pins,
|
| 986 | #ifdef CONFIG_DEBUG_FS
|
| 987 | .pin_dbg_show = sppctl_pin_dbg_show,
|
| 988 | #endif
|
| 989 | .dt_node_to_map = sppctl_dt_node_to_map,
|
| 990 | .dt_free_map = pinctrl_utils_free_map,
|
| 991 | };
|
| 992 |
|
| 993 | static int sppctl_group_groups(struct platform_device *pdev)
|
| 994 | {
|
| 995 | struct sppctl_pdata *sppctl = platform_get_drvdata(pdev);
|
| 996 | int i, k, j;
|
| 997 |
|
| 998 |
|
| 999 | sppctl->unq_grps_sz = sppctl_gpio_list_sz;
|
| 1000 | for (i = 0; i < sppctl_list_funcs_sz; i++)
|
| 1001 | if (sppctl_list_funcs[i].type == pinmux_type_grp)
|
| 1002 | sppctl->unq_grps_sz += sppctl_list_funcs[i].gnum;
|
| 1003 |
|
| 1004 | sppctl->unq_grps = devm_kcalloc(&pdev->dev, sppctl->unq_grps_sz + 1,
|
| 1005 | sizeof(*sppctl->unq_grps), GFP_KERNEL);
|
| 1006 | if (!sppctl->unq_grps)
|
| 1007 | return -ENOMEM;
|
| 1008 |
|
| 1009 | sppctl->g2fp_maps = devm_kcalloc(&pdev->dev, sppctl->unq_grps_sz + 1,
|
| 1010 | sizeof(*sppctl->g2fp_maps), GFP_KERNEL);
|
| 1011 | if (!sppctl->g2fp_maps)
|
| 1012 | return -ENOMEM;
|
| 1013 |
|
| 1014 |
|
| 1015 | for (i = 0; i < sppctl_gpio_list_sz; i++) {
|
| 1016 | sppctl->unq_grps[i] = sppctl_gpio_list_s[i];
|
| 1017 | sppctl->g2fp_maps[i].f_idx = 0;
|
| 1018 | sppctl->g2fp_maps[i].g_idx = i;
|
| 1019 | }
|
| 1020 |
|
| 1021 |
|
| 1022 | j = sppctl_gpio_list_sz;
|
| 1023 | for (i = 0; i < sppctl_list_funcs_sz; i++) {
|
| 1024 | if (sppctl_list_funcs[i].type != pinmux_type_grp)
|
| 1025 | continue;
|
| 1026 |
|
| 1027 | for (k = 0; k < sppctl_list_funcs[i].gnum; k++) {
|
| 1028 | sppctl->unq_grps[j] = sppctl_list_funcs[i].grps[k].name;
|
| 1029 | sppctl->g2fp_maps[j].f_idx = i;
|
| 1030 | sppctl->g2fp_maps[j].g_idx = k;
|
| 1031 | j++;
|
| 1032 | }
|
| 1033 | }
|
| 1034 |
|
| 1035 | return 0;
|
| 1036 | }
|
| 1037 |
|
| 1038 | static int sppctl_pinctrl_init(struct platform_device *pdev)
|
| 1039 | {
|
| 1040 | struct sppctl_pdata *sppctl = platform_get_drvdata(pdev);
|
| 1041 | int err;
|
| 1042 |
|
| 1043 | sppctl->pctl_desc.owner = THIS_MODULE;
|
| 1044 | sppctl->pctl_desc.name = dev_name(&pdev->dev);
|
| 1045 | sppctl->pctl_desc.pins = sppctl_pins_all;
|
| 1046 | sppctl->pctl_desc.npins = sppctl_pins_all_sz;
|
| 1047 | sppctl->pctl_desc.pctlops = &sppctl_pctl_ops;
|
| 1048 | sppctl->pctl_desc.confops = &sppctl_pconf_ops;
|
| 1049 | sppctl->pctl_desc.pmxops = &sppctl_pinmux_ops;
|
| 1050 |
|
| 1051 | err = sppctl_group_groups(pdev);
|
| 1052 | if (err)
|
| 1053 | return err;
|
| 1054 |
|
| 1055 | err = devm_pinctrl_register_and_init(&pdev->dev, &sppctl->pctl_desc,
|
| 1056 | sppctl, &sppctl->pctl_dev);
|
| 1057 | if (err)
|
| 1058 | return dev_err_probe(&pdev->dev, err, "Failed to register pinctrl!\n");
|
| 1059 |
|
| 1060 | pinctrl_enable(sppctl->pctl_dev);
|
| 1061 | return 0;
|
| 1062 | }
|
| 1063 |
|
| 1064 | static int sppctl_resource_map(struct platform_device *pdev, struct sppctl_pdata *sppctl)
|
| 1065 | {
|
| 1066 | sppctl->moon2_base = devm_platform_ioremap_resource_byname(pdev, "moon2");
|
| 1067 | if (IS_ERR(sppctl->moon2_base))
|
| 1068 | return PTR_ERR(sppctl->moon2_base);
|
| 1069 |
|
| 1070 | sppctl->gpioxt_base = devm_platform_ioremap_resource_byname(pdev, "gpioxt");
|
| 1071 | if (IS_ERR(sppctl->gpioxt_base))
|
| 1072 | return PTR_ERR(sppctl->gpioxt_base);
|
| 1073 |
|
| 1074 | sppctl->first_base = devm_platform_ioremap_resource_byname(pdev, "first");
|
| 1075 | if (IS_ERR(sppctl->first_base))
|
| 1076 | return PTR_ERR(sppctl->first_base);
|
| 1077 |
|
| 1078 | sppctl->moon1_base = devm_platform_ioremap_resource_byname(pdev, "moon1");
|
| 1079 | if (IS_ERR(sppctl->moon1_base))
|
| 1080 | return PTR_ERR(sppctl->moon1_base);
|
| 1081 |
|
| 1082 | return 0;
|
| 1083 | }
|
| 1084 |
|
| 1085 | static int sppctl_probe(struct platform_device *pdev)
|
| 1086 | {
|
| 1087 | struct sppctl_pdata *sppctl;
|
| 1088 | int ret;
|
| 1089 |
|
| 1090 | sppctl = devm_kzalloc(&pdev->dev, sizeof(*sppctl), GFP_KERNEL);
|
| 1091 | if (!sppctl)
|
| 1092 | return -ENOMEM;
|
| 1093 | platform_set_drvdata(pdev, sppctl);
|
| 1094 |
|
| 1095 | ret = sppctl_resource_map(pdev, sppctl);
|
| 1096 | if (ret)
|
| 1097 | return ret;
|
| 1098 |
|
| 1099 | ret = sppctl_gpio_new(pdev, sppctl);
|
| 1100 | if (ret)
|
| 1101 | return ret;
|
| 1102 |
|
| 1103 | ret = sppctl_pinctrl_init(pdev);
|
| 1104 | if (ret)
|
| 1105 | return ret;
|
| 1106 |
|
| 1107 | pinctrl_add_gpio_range(sppctl->pctl_dev, &sppctl->pctl_grange);
|
| 1108 |
|
| 1109 | return 0;
|
| 1110 | }
|
| 1111 |
|
| 1112 | static const struct of_device_id sppctl_match_table[] = {
|
| 1113 | { .compatible = "sunplus,sp7021-pctl" },
|
| 1114 | { }
|
| 1115 | };
|
| 1116 |
|
| 1117 | static struct platform_driver sppctl_pinctrl_driver = {
|
| 1118 | .driver = {
|
| 1119 | .name = SPPCTL_MODULE_NAME,
|
| 1120 | .of_match_table = sppctl_match_table,
|
| 1121 | },
|
| 1122 | .probe = sppctl_probe,
|
| 1123 | };
|
| 1124 | builtin_platform_driver(sppctl_pinctrl_driver)
|
| 1125 |
|
| 1126 | MODULE_AUTHOR("Dvorkin Dmitry <[email protected]>");
|
| 1127 | MODULE_AUTHOR("Wells Lu <[email protected]>");
|
| 1128 | MODULE_DESCRIPTION("Sunplus SP7021 Pin Control and GPIO driver");
|
| 1129 | MODULE_LICENSE("GPL v2");
|