Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

pinctrl: bcm: add driver for BCM4908 pinmux

BCM4908 has its own pins layout so it needs a custom binding and a Linux
driver.

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Link: https://lore.kernel.org/r/20220124102243.14912-2-zajec5@gmail.com
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

authored by

Rafał Miłecki and committed by
Linus Walleij
f7e322d9 7b5730f0

+579
+1
MAINTAINERS
··· 3694 3694 L: linux-gpio@vger.kernel.org 3695 3695 S: Maintained 3696 3696 F: Documentation/devicetree/bindings/pinctrl/brcm,bcm4908-pinctrl.yaml 3697 + F: drivers/pinctrl/bcm/pinctrl-bcm4908.c 3697 3698 3698 3699 BROADCOM BCM5301X ARM ARCHITECTURE 3699 3700 M: Florian Fainelli <f.fainelli@gmail.com>
+14
drivers/pinctrl/bcm/Kconfig
··· 29 29 help 30 30 Say Y here to enable the Broadcom BCM2835 GPIO driver. 31 31 32 + config PINCTRL_BCM4908 33 + tristate "Broadcom BCM4908 pinmux driver" 34 + depends on OF && (ARCH_BCM4908 || COMPILE_TEST) 35 + select PINMUX 36 + select PINCONF 37 + select GENERIC_PINCONF 38 + select GENERIC_PINCTRL_GROUPS 39 + select GENERIC_PINMUX_FUNCTIONS 40 + default ARCH_BCM4908 41 + help 42 + Driver for BCM4908 family SoCs with integrated pin controller. 43 + 44 + If compiled as module it will be called pinctrl-bcm4908. 45 + 32 46 config PINCTRL_BCM63XX 33 47 bool 34 48 select PINMUX
+1
drivers/pinctrl/bcm/Makefile
··· 3 3 4 4 obj-$(CONFIG_PINCTRL_BCM281XX) += pinctrl-bcm281xx.o 5 5 obj-$(CONFIG_PINCTRL_BCM2835) += pinctrl-bcm2835.o 6 + obj-$(CONFIG_PINCTRL_BCM4908) += pinctrl-bcm4908.o 6 7 obj-$(CONFIG_PINCTRL_BCM63XX) += pinctrl-bcm63xx.o 7 8 obj-$(CONFIG_PINCTRL_BCM6318) += pinctrl-bcm6318.o 8 9 obj-$(CONFIG_PINCTRL_BCM6328) += pinctrl-bcm6328.o
+563
drivers/pinctrl/bcm/pinctrl-bcm4908.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (C) 2021 Rafał Miłecki <rafal@milecki.pl> */ 3 + 4 + #include <linux/err.h> 5 + #include <linux/io.h> 6 + #include <linux/mod_devicetable.h> 7 + #include <linux/module.h> 8 + #include <linux/pinctrl/pinconf-generic.h> 9 + #include <linux/pinctrl/pinctrl.h> 10 + #include <linux/pinctrl/pinmux.h> 11 + #include <linux/platform_device.h> 12 + #include <linux/slab.h> 13 + #include <linux/string_helpers.h> 14 + 15 + #include "../core.h" 16 + #include "../pinmux.h" 17 + 18 + #define BCM4908_NUM_PINS 86 19 + 20 + #define BCM4908_TEST_PORT_BLOCK_EN_LSB 0x00 21 + #define BCM4908_TEST_PORT_BLOCK_DATA_MSB 0x04 22 + #define BCM4908_TEST_PORT_BLOCK_DATA_LSB 0x08 23 + #define BCM4908_TEST_PORT_LSB_PINMUX_DATA_SHIFT 12 24 + #define BCM4908_TEST_PORT_COMMAND 0x0c 25 + #define BCM4908_TEST_PORT_CMD_LOAD_MUX_REG 0x00000021 26 + 27 + struct bcm4908_pinctrl { 28 + struct device *dev; 29 + void __iomem *base; 30 + struct mutex mutex; 31 + struct pinctrl_dev *pctldev; 32 + struct pinctrl_desc pctldesc; 33 + }; 34 + 35 + /* 36 + * Groups 37 + */ 38 + 39 + struct bcm4908_pinctrl_pin_setup { 40 + unsigned int number; 41 + unsigned int function; 42 + }; 43 + 44 + static const struct bcm4908_pinctrl_pin_setup led_0_pins_a[] = { 45 + { 0, 3 }, 46 + }; 47 + 48 + static const struct bcm4908_pinctrl_pin_setup led_1_pins_a[] = { 49 + { 1, 3 }, 50 + }; 51 + 52 + static const struct bcm4908_pinctrl_pin_setup led_2_pins_a[] = { 53 + { 2, 3 }, 54 + }; 55 + 56 + static const struct bcm4908_pinctrl_pin_setup led_3_pins_a[] = { 57 + { 3, 3 }, 58 + }; 59 + 60 + static const struct bcm4908_pinctrl_pin_setup led_4_pins_a[] = { 61 + { 4, 3 }, 62 + }; 63 + 64 + static const struct bcm4908_pinctrl_pin_setup led_5_pins_a[] = { 65 + { 5, 3 }, 66 + }; 67 + 68 + static const struct bcm4908_pinctrl_pin_setup led_6_pins_a[] = { 69 + { 6, 3 }, 70 + }; 71 + 72 + static const struct bcm4908_pinctrl_pin_setup led_7_pins_a[] = { 73 + { 7, 3 }, 74 + }; 75 + 76 + static const struct bcm4908_pinctrl_pin_setup led_8_pins_a[] = { 77 + { 8, 3 }, 78 + }; 79 + 80 + static const struct bcm4908_pinctrl_pin_setup led_9_pins_a[] = { 81 + { 9, 3 }, 82 + }; 83 + 84 + static const struct bcm4908_pinctrl_pin_setup led_10_pins_a[] = { 85 + { 10, 3 }, 86 + }; 87 + 88 + static const struct bcm4908_pinctrl_pin_setup led_11_pins_a[] = { 89 + { 11, 3 }, 90 + }; 91 + 92 + static const struct bcm4908_pinctrl_pin_setup led_12_pins_a[] = { 93 + { 12, 3 }, 94 + }; 95 + 96 + static const struct bcm4908_pinctrl_pin_setup led_13_pins_a[] = { 97 + { 13, 3 }, 98 + }; 99 + 100 + static const struct bcm4908_pinctrl_pin_setup led_14_pins_a[] = { 101 + { 14, 3 }, 102 + }; 103 + 104 + static const struct bcm4908_pinctrl_pin_setup led_15_pins_a[] = { 105 + { 15, 3 }, 106 + }; 107 + 108 + static const struct bcm4908_pinctrl_pin_setup led_16_pins_a[] = { 109 + { 16, 3 }, 110 + }; 111 + 112 + static const struct bcm4908_pinctrl_pin_setup led_17_pins_a[] = { 113 + { 17, 3 }, 114 + }; 115 + 116 + static const struct bcm4908_pinctrl_pin_setup led_18_pins_a[] = { 117 + { 18, 3 }, 118 + }; 119 + 120 + static const struct bcm4908_pinctrl_pin_setup led_19_pins_a[] = { 121 + { 19, 3 }, 122 + }; 123 + 124 + static const struct bcm4908_pinctrl_pin_setup led_20_pins_a[] = { 125 + { 20, 3 }, 126 + }; 127 + 128 + static const struct bcm4908_pinctrl_pin_setup led_21_pins_a[] = { 129 + { 21, 3 }, 130 + }; 131 + 132 + static const struct bcm4908_pinctrl_pin_setup led_22_pins_a[] = { 133 + { 22, 3 }, 134 + }; 135 + 136 + static const struct bcm4908_pinctrl_pin_setup led_23_pins_a[] = { 137 + { 23, 3 }, 138 + }; 139 + 140 + static const struct bcm4908_pinctrl_pin_setup led_24_pins_a[] = { 141 + { 24, 3 }, 142 + }; 143 + 144 + static const struct bcm4908_pinctrl_pin_setup led_25_pins_a[] = { 145 + { 25, 3 }, 146 + }; 147 + 148 + static const struct bcm4908_pinctrl_pin_setup led_26_pins_a[] = { 149 + { 26, 3 }, 150 + }; 151 + 152 + static const struct bcm4908_pinctrl_pin_setup led_27_pins_a[] = { 153 + { 27, 3 }, 154 + }; 155 + 156 + static const struct bcm4908_pinctrl_pin_setup led_28_pins_a[] = { 157 + { 28, 3 }, 158 + }; 159 + 160 + static const struct bcm4908_pinctrl_pin_setup led_29_pins_a[] = { 161 + { 29, 3 }, 162 + }; 163 + 164 + static const struct bcm4908_pinctrl_pin_setup led_30_pins_a[] = { 165 + { 30, 3 }, 166 + }; 167 + 168 + static const struct bcm4908_pinctrl_pin_setup led_31_pins_a[] = { 169 + { 31, 3 }, 170 + }; 171 + 172 + static const struct bcm4908_pinctrl_pin_setup led_10_pins_b[] = { 173 + { 8, 2 }, 174 + }; 175 + 176 + static const struct bcm4908_pinctrl_pin_setup led_11_pins_b[] = { 177 + { 9, 2 }, 178 + }; 179 + 180 + static const struct bcm4908_pinctrl_pin_setup led_12_pins_b[] = { 181 + { 0, 2 }, 182 + }; 183 + 184 + static const struct bcm4908_pinctrl_pin_setup led_13_pins_b[] = { 185 + { 1, 2 }, 186 + }; 187 + 188 + static const struct bcm4908_pinctrl_pin_setup led_31_pins_b[] = { 189 + { 30, 2 }, 190 + }; 191 + 192 + static const struct bcm4908_pinctrl_pin_setup hs_uart_pins[] = { 193 + { 10, 0 }, /* CTS */ 194 + { 11, 0 }, /* RTS */ 195 + { 12, 0 }, /* RXD */ 196 + { 13, 0 }, /* TXD */ 197 + }; 198 + 199 + static const struct bcm4908_pinctrl_pin_setup i2c_pins_a[] = { 200 + { 18, 0 }, /* SDA */ 201 + { 19, 0 }, /* SCL */ 202 + }; 203 + 204 + static const struct bcm4908_pinctrl_pin_setup i2c_pins_b[] = { 205 + { 22, 0 }, /* SDA */ 206 + { 23, 0 }, /* SCL */ 207 + }; 208 + 209 + static const struct bcm4908_pinctrl_pin_setup i2s_pins[] = { 210 + { 27, 0 }, /* MCLK */ 211 + { 28, 0 }, /* LRCK */ 212 + { 29, 0 }, /* SDATA */ 213 + { 30, 0 }, /* SCLK */ 214 + }; 215 + 216 + static const struct bcm4908_pinctrl_pin_setup nand_ctrl_pins[] = { 217 + { 32, 0 }, 218 + { 33, 0 }, 219 + { 34, 0 }, 220 + { 43, 0 }, 221 + { 44, 0 }, 222 + { 45, 0 }, 223 + { 56, 1 }, 224 + }; 225 + 226 + static const struct bcm4908_pinctrl_pin_setup nand_data_pins[] = { 227 + { 35, 0 }, 228 + { 36, 0 }, 229 + { 37, 0 }, 230 + { 38, 0 }, 231 + { 39, 0 }, 232 + { 40, 0 }, 233 + { 41, 0 }, 234 + { 42, 0 }, 235 + }; 236 + 237 + static const struct bcm4908_pinctrl_pin_setup emmc_ctrl_pins[] = { 238 + { 46, 0 }, 239 + { 47, 0 }, 240 + }; 241 + 242 + static const struct bcm4908_pinctrl_pin_setup usb0_pwr_pins[] = { 243 + { 63, 0 }, 244 + { 64, 0 }, 245 + }; 246 + 247 + static const struct bcm4908_pinctrl_pin_setup usb1_pwr_pins[] = { 248 + { 66, 0 }, 249 + { 67, 0 }, 250 + }; 251 + 252 + struct bcm4908_pinctrl_grp { 253 + const char *name; 254 + const struct bcm4908_pinctrl_pin_setup *pins; 255 + const unsigned int num_pins; 256 + }; 257 + 258 + static const struct bcm4908_pinctrl_grp bcm4908_pinctrl_grps[] = { 259 + { "led_0_grp_a", led_0_pins_a, ARRAY_SIZE(led_0_pins_a) }, 260 + { "led_1_grp_a", led_1_pins_a, ARRAY_SIZE(led_1_pins_a) }, 261 + { "led_2_grp_a", led_2_pins_a, ARRAY_SIZE(led_2_pins_a) }, 262 + { "led_3_grp_a", led_3_pins_a, ARRAY_SIZE(led_3_pins_a) }, 263 + { "led_4_grp_a", led_4_pins_a, ARRAY_SIZE(led_4_pins_a) }, 264 + { "led_5_grp_a", led_5_pins_a, ARRAY_SIZE(led_5_pins_a) }, 265 + { "led_6_grp_a", led_6_pins_a, ARRAY_SIZE(led_6_pins_a) }, 266 + { "led_7_grp_a", led_7_pins_a, ARRAY_SIZE(led_7_pins_a) }, 267 + { "led_8_grp_a", led_8_pins_a, ARRAY_SIZE(led_8_pins_a) }, 268 + { "led_9_grp_a", led_9_pins_a, ARRAY_SIZE(led_9_pins_a) }, 269 + { "led_10_grp_a", led_10_pins_a, ARRAY_SIZE(led_10_pins_a) }, 270 + { "led_11_grp_a", led_11_pins_a, ARRAY_SIZE(led_11_pins_a) }, 271 + { "led_12_grp_a", led_12_pins_a, ARRAY_SIZE(led_12_pins_a) }, 272 + { "led_13_grp_a", led_13_pins_a, ARRAY_SIZE(led_13_pins_a) }, 273 + { "led_14_grp_a", led_14_pins_a, ARRAY_SIZE(led_14_pins_a) }, 274 + { "led_15_grp_a", led_15_pins_a, ARRAY_SIZE(led_15_pins_a) }, 275 + { "led_16_grp_a", led_16_pins_a, ARRAY_SIZE(led_16_pins_a) }, 276 + { "led_17_grp_a", led_17_pins_a, ARRAY_SIZE(led_17_pins_a) }, 277 + { "led_18_grp_a", led_18_pins_a, ARRAY_SIZE(led_18_pins_a) }, 278 + { "led_19_grp_a", led_19_pins_a, ARRAY_SIZE(led_19_pins_a) }, 279 + { "led_20_grp_a", led_20_pins_a, ARRAY_SIZE(led_20_pins_a) }, 280 + { "led_21_grp_a", led_21_pins_a, ARRAY_SIZE(led_21_pins_a) }, 281 + { "led_22_grp_a", led_22_pins_a, ARRAY_SIZE(led_22_pins_a) }, 282 + { "led_23_grp_a", led_23_pins_a, ARRAY_SIZE(led_23_pins_a) }, 283 + { "led_24_grp_a", led_24_pins_a, ARRAY_SIZE(led_24_pins_a) }, 284 + { "led_25_grp_a", led_25_pins_a, ARRAY_SIZE(led_25_pins_a) }, 285 + { "led_26_grp_a", led_26_pins_a, ARRAY_SIZE(led_26_pins_a) }, 286 + { "led_27_grp_a", led_27_pins_a, ARRAY_SIZE(led_27_pins_a) }, 287 + { "led_28_grp_a", led_28_pins_a, ARRAY_SIZE(led_28_pins_a) }, 288 + { "led_29_grp_a", led_29_pins_a, ARRAY_SIZE(led_29_pins_a) }, 289 + { "led_30_grp_a", led_30_pins_a, ARRAY_SIZE(led_30_pins_a) }, 290 + { "led_31_grp_a", led_31_pins_a, ARRAY_SIZE(led_31_pins_a) }, 291 + { "led_10_grp_b", led_10_pins_b, ARRAY_SIZE(led_10_pins_b) }, 292 + { "led_11_grp_b", led_11_pins_b, ARRAY_SIZE(led_11_pins_b) }, 293 + { "led_12_grp_b", led_12_pins_b, ARRAY_SIZE(led_12_pins_b) }, 294 + { "led_13_grp_b", led_13_pins_b, ARRAY_SIZE(led_13_pins_b) }, 295 + { "led_31_grp_b", led_31_pins_b, ARRAY_SIZE(led_31_pins_b) }, 296 + { "hs_uart_grp", hs_uart_pins, ARRAY_SIZE(hs_uart_pins) }, 297 + { "i2c_grp_a", i2c_pins_a, ARRAY_SIZE(i2c_pins_a) }, 298 + { "i2c_grp_b", i2c_pins_b, ARRAY_SIZE(i2c_pins_b) }, 299 + { "i2s_grp", i2s_pins, ARRAY_SIZE(i2s_pins) }, 300 + { "nand_ctrl_grp", nand_ctrl_pins, ARRAY_SIZE(nand_ctrl_pins) }, 301 + { "nand_data_grp", nand_data_pins, ARRAY_SIZE(nand_data_pins) }, 302 + { "emmc_ctrl_grp", emmc_ctrl_pins, ARRAY_SIZE(emmc_ctrl_pins) }, 303 + { "usb0_pwr_grp", usb0_pwr_pins, ARRAY_SIZE(usb0_pwr_pins) }, 304 + { "usb1_pwr_grp", usb1_pwr_pins, ARRAY_SIZE(usb1_pwr_pins) }, 305 + }; 306 + 307 + /* 308 + * Functions 309 + */ 310 + 311 + struct bcm4908_pinctrl_function { 312 + const char *name; 313 + const char * const *groups; 314 + const unsigned int num_groups; 315 + }; 316 + 317 + static const char * const led_0_groups[] = { "led_0_grp_a" }; 318 + static const char * const led_1_groups[] = { "led_1_grp_a" }; 319 + static const char * const led_2_groups[] = { "led_2_grp_a" }; 320 + static const char * const led_3_groups[] = { "led_3_grp_a" }; 321 + static const char * const led_4_groups[] = { "led_4_grp_a" }; 322 + static const char * const led_5_groups[] = { "led_5_grp_a" }; 323 + static const char * const led_6_groups[] = { "led_6_grp_a" }; 324 + static const char * const led_7_groups[] = { "led_7_grp_a" }; 325 + static const char * const led_8_groups[] = { "led_8_grp_a" }; 326 + static const char * const led_9_groups[] = { "led_9_grp_a" }; 327 + static const char * const led_10_groups[] = { "led_10_grp_a", "led_10_grp_b" }; 328 + static const char * const led_11_groups[] = { "led_11_grp_a", "led_11_grp_b" }; 329 + static const char * const led_12_groups[] = { "led_12_grp_a", "led_12_grp_b" }; 330 + static const char * const led_13_groups[] = { "led_13_grp_a", "led_13_grp_b" }; 331 + static const char * const led_14_groups[] = { "led_14_grp_a" }; 332 + static const char * const led_15_groups[] = { "led_15_grp_a" }; 333 + static const char * const led_16_groups[] = { "led_16_grp_a" }; 334 + static const char * const led_17_groups[] = { "led_17_grp_a" }; 335 + static const char * const led_18_groups[] = { "led_18_grp_a" }; 336 + static const char * const led_19_groups[] = { "led_19_grp_a" }; 337 + static const char * const led_20_groups[] = { "led_20_grp_a" }; 338 + static const char * const led_21_groups[] = { "led_21_grp_a" }; 339 + static const char * const led_22_groups[] = { "led_22_grp_a" }; 340 + static const char * const led_23_groups[] = { "led_23_grp_a" }; 341 + static const char * const led_24_groups[] = { "led_24_grp_a" }; 342 + static const char * const led_25_groups[] = { "led_25_grp_a" }; 343 + static const char * const led_26_groups[] = { "led_26_grp_a" }; 344 + static const char * const led_27_groups[] = { "led_27_grp_a" }; 345 + static const char * const led_28_groups[] = { "led_28_grp_a" }; 346 + static const char * const led_29_groups[] = { "led_29_grp_a" }; 347 + static const char * const led_30_groups[] = { "led_30_grp_a" }; 348 + static const char * const led_31_groups[] = { "led_31_grp_a", "led_31_grp_b" }; 349 + static const char * const hs_uart_groups[] = { "hs_uart_grp" }; 350 + static const char * const i2c_groups[] = { "i2c_grp_a", "i2c_grp_b" }; 351 + static const char * const i2s_groups[] = { "i2s_grp" }; 352 + static const char * const nand_ctrl_groups[] = { "nand_ctrl_grp" }; 353 + static const char * const nand_data_groups[] = { "nand_data_grp" }; 354 + static const char * const emmc_ctrl_groups[] = { "emmc_ctrl_grp" }; 355 + static const char * const usb0_pwr_groups[] = { "usb0_pwr_grp" }; 356 + static const char * const usb1_pwr_groups[] = { "usb1_pwr_grp" }; 357 + 358 + static const struct bcm4908_pinctrl_function bcm4908_pinctrl_functions[] = { 359 + { "led_0", led_0_groups, ARRAY_SIZE(led_0_groups) }, 360 + { "led_1", led_1_groups, ARRAY_SIZE(led_1_groups) }, 361 + { "led_2", led_2_groups, ARRAY_SIZE(led_2_groups) }, 362 + { "led_3", led_3_groups, ARRAY_SIZE(led_3_groups) }, 363 + { "led_4", led_4_groups, ARRAY_SIZE(led_4_groups) }, 364 + { "led_5", led_5_groups, ARRAY_SIZE(led_5_groups) }, 365 + { "led_6", led_6_groups, ARRAY_SIZE(led_6_groups) }, 366 + { "led_7", led_7_groups, ARRAY_SIZE(led_7_groups) }, 367 + { "led_8", led_8_groups, ARRAY_SIZE(led_8_groups) }, 368 + { "led_9", led_9_groups, ARRAY_SIZE(led_9_groups) }, 369 + { "led_10", led_10_groups, ARRAY_SIZE(led_10_groups) }, 370 + { "led_11", led_11_groups, ARRAY_SIZE(led_11_groups) }, 371 + { "led_12", led_12_groups, ARRAY_SIZE(led_12_groups) }, 372 + { "led_13", led_13_groups, ARRAY_SIZE(led_13_groups) }, 373 + { "led_14", led_14_groups, ARRAY_SIZE(led_14_groups) }, 374 + { "led_15", led_15_groups, ARRAY_SIZE(led_15_groups) }, 375 + { "led_16", led_16_groups, ARRAY_SIZE(led_16_groups) }, 376 + { "led_17", led_17_groups, ARRAY_SIZE(led_17_groups) }, 377 + { "led_18", led_18_groups, ARRAY_SIZE(led_18_groups) }, 378 + { "led_19", led_19_groups, ARRAY_SIZE(led_19_groups) }, 379 + { "led_20", led_20_groups, ARRAY_SIZE(led_20_groups) }, 380 + { "led_21", led_21_groups, ARRAY_SIZE(led_21_groups) }, 381 + { "led_22", led_22_groups, ARRAY_SIZE(led_22_groups) }, 382 + { "led_23", led_23_groups, ARRAY_SIZE(led_23_groups) }, 383 + { "led_24", led_24_groups, ARRAY_SIZE(led_24_groups) }, 384 + { "led_25", led_25_groups, ARRAY_SIZE(led_25_groups) }, 385 + { "led_26", led_26_groups, ARRAY_SIZE(led_26_groups) }, 386 + { "led_27", led_27_groups, ARRAY_SIZE(led_27_groups) }, 387 + { "led_28", led_28_groups, ARRAY_SIZE(led_28_groups) }, 388 + { "led_29", led_29_groups, ARRAY_SIZE(led_29_groups) }, 389 + { "led_30", led_30_groups, ARRAY_SIZE(led_30_groups) }, 390 + { "led_31", led_31_groups, ARRAY_SIZE(led_31_groups) }, 391 + { "hs_uart", hs_uart_groups, ARRAY_SIZE(hs_uart_groups) }, 392 + { "i2c", i2c_groups, ARRAY_SIZE(i2c_groups) }, 393 + { "i2s", i2s_groups, ARRAY_SIZE(i2s_groups) }, 394 + { "nand_ctrl", nand_ctrl_groups, ARRAY_SIZE(nand_ctrl_groups) }, 395 + { "nand_data", nand_data_groups, ARRAY_SIZE(nand_data_groups) }, 396 + { "emmc_ctrl", emmc_ctrl_groups, ARRAY_SIZE(emmc_ctrl_groups) }, 397 + { "usb0_pwr", usb0_pwr_groups, ARRAY_SIZE(usb0_pwr_groups) }, 398 + { "usb1_pwr", usb1_pwr_groups, ARRAY_SIZE(usb1_pwr_groups) }, 399 + }; 400 + 401 + /* 402 + * Groups code 403 + */ 404 + 405 + static const struct pinctrl_ops bcm4908_pinctrl_ops = { 406 + .get_groups_count = pinctrl_generic_get_group_count, 407 + .get_group_name = pinctrl_generic_get_group_name, 408 + .get_group_pins = pinctrl_generic_get_group_pins, 409 + .dt_node_to_map = pinconf_generic_dt_node_to_map_group, 410 + .dt_free_map = pinconf_generic_dt_free_map, 411 + }; 412 + 413 + /* 414 + * Functions code 415 + */ 416 + 417 + static int bcm4908_pinctrl_set_mux(struct pinctrl_dev *pctrl_dev, 418 + unsigned int func_selector, 419 + unsigned int group_selector) 420 + { 421 + struct bcm4908_pinctrl *bcm4908_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); 422 + const struct bcm4908_pinctrl_grp *group; 423 + struct group_desc *group_desc; 424 + int i; 425 + 426 + group_desc = pinctrl_generic_get_group(pctrl_dev, group_selector); 427 + if (!group_desc) 428 + return -EINVAL; 429 + group = group_desc->data; 430 + 431 + mutex_lock(&bcm4908_pinctrl->mutex); 432 + for (i = 0; i < group->num_pins; i++) { 433 + u32 lsb = 0; 434 + 435 + lsb |= group->pins[i].number; 436 + lsb |= group->pins[i].function << BCM4908_TEST_PORT_LSB_PINMUX_DATA_SHIFT; 437 + 438 + writel(0x0, bcm4908_pinctrl->base + BCM4908_TEST_PORT_BLOCK_DATA_MSB); 439 + writel(lsb, bcm4908_pinctrl->base + BCM4908_TEST_PORT_BLOCK_DATA_LSB); 440 + writel(BCM4908_TEST_PORT_CMD_LOAD_MUX_REG, 441 + bcm4908_pinctrl->base + BCM4908_TEST_PORT_COMMAND); 442 + } 443 + mutex_unlock(&bcm4908_pinctrl->mutex); 444 + 445 + return 0; 446 + } 447 + 448 + static const struct pinmux_ops bcm4908_pinctrl_pmxops = { 449 + .get_functions_count = pinmux_generic_get_function_count, 450 + .get_function_name = pinmux_generic_get_function_name, 451 + .get_function_groups = pinmux_generic_get_function_groups, 452 + .set_mux = bcm4908_pinctrl_set_mux, 453 + }; 454 + 455 + /* 456 + * Controller code 457 + */ 458 + 459 + static struct pinctrl_desc bcm4908_pinctrl_desc = { 460 + .name = "bcm4908-pinctrl", 461 + .pctlops = &bcm4908_pinctrl_ops, 462 + .pmxops = &bcm4908_pinctrl_pmxops, 463 + }; 464 + 465 + static const struct of_device_id bcm4908_pinctrl_of_match_table[] = { 466 + { .compatible = "brcm,bcm4908-pinctrl", }, 467 + { } 468 + }; 469 + 470 + static int bcm4908_pinctrl_probe(struct platform_device *pdev) 471 + { 472 + struct device *dev = &pdev->dev; 473 + struct bcm4908_pinctrl *bcm4908_pinctrl; 474 + struct pinctrl_desc *pctldesc; 475 + struct pinctrl_pin_desc *pins; 476 + char **pin_names; 477 + int i; 478 + 479 + bcm4908_pinctrl = devm_kzalloc(dev, sizeof(*bcm4908_pinctrl), GFP_KERNEL); 480 + if (!bcm4908_pinctrl) 481 + return -ENOMEM; 482 + pctldesc = &bcm4908_pinctrl->pctldesc; 483 + platform_set_drvdata(pdev, bcm4908_pinctrl); 484 + 485 + /* Set basic properties */ 486 + 487 + bcm4908_pinctrl->dev = dev; 488 + 489 + bcm4908_pinctrl->base = devm_platform_ioremap_resource(pdev, 0); 490 + if (IS_ERR(bcm4908_pinctrl->base)) 491 + return PTR_ERR(bcm4908_pinctrl->base); 492 + 493 + mutex_init(&bcm4908_pinctrl->mutex); 494 + 495 + memcpy(pctldesc, &bcm4908_pinctrl_desc, sizeof(*pctldesc)); 496 + 497 + /* Set pinctrl properties */ 498 + 499 + pin_names = devm_kasprintf_strarray(dev, "pin", BCM4908_NUM_PINS); 500 + if (IS_ERR(pin_names)) 501 + return PTR_ERR(pin_names); 502 + 503 + pins = devm_kcalloc(dev, BCM4908_NUM_PINS, sizeof(*pins), GFP_KERNEL); 504 + if (!pins) 505 + return -ENOMEM; 506 + for (i = 0; i < BCM4908_NUM_PINS; i++) { 507 + pins[i].number = i; 508 + pins[i].name = pin_names[i]; 509 + } 510 + pctldesc->pins = pins; 511 + pctldesc->npins = BCM4908_NUM_PINS; 512 + 513 + /* Register */ 514 + 515 + bcm4908_pinctrl->pctldev = devm_pinctrl_register(dev, pctldesc, bcm4908_pinctrl); 516 + if (IS_ERR(bcm4908_pinctrl->pctldev)) 517 + return dev_err_probe(dev, PTR_ERR(bcm4908_pinctrl->pctldev), 518 + "Failed to register pinctrl\n"); 519 + 520 + /* Groups */ 521 + 522 + for (i = 0; i < ARRAY_SIZE(bcm4908_pinctrl_grps); i++) { 523 + const struct bcm4908_pinctrl_grp *group = &bcm4908_pinctrl_grps[i]; 524 + int *pins; 525 + int j; 526 + 527 + pins = devm_kcalloc(dev, group->num_pins, sizeof(*pins), GFP_KERNEL); 528 + if (!pins) 529 + return -ENOMEM; 530 + for (j = 0; j < group->num_pins; j++) 531 + pins[j] = group->pins[j].number; 532 + 533 + pinctrl_generic_add_group(bcm4908_pinctrl->pctldev, group->name, 534 + pins, group->num_pins, (void *)group); 535 + } 536 + 537 + /* Functions */ 538 + 539 + for (i = 0; i < ARRAY_SIZE(bcm4908_pinctrl_functions); i++) { 540 + const struct bcm4908_pinctrl_function *function = &bcm4908_pinctrl_functions[i]; 541 + 542 + pinmux_generic_add_function(bcm4908_pinctrl->pctldev, 543 + function->name, 544 + function->groups, 545 + function->num_groups, NULL); 546 + } 547 + 548 + return 0; 549 + } 550 + 551 + static struct platform_driver bcm4908_pinctrl_driver = { 552 + .probe = bcm4908_pinctrl_probe, 553 + .driver = { 554 + .name = "bcm4908-pinctrl", 555 + .of_match_table = bcm4908_pinctrl_of_match_table, 556 + }, 557 + }; 558 + 559 + module_platform_driver(bcm4908_pinctrl_driver); 560 + 561 + MODULE_AUTHOR("Rafał Miłecki"); 562 + MODULE_LICENSE("GPL v2"); 563 + MODULE_DEVICE_TABLE(of, bcm4908_pinctrl_of_match_table);