1b5c23aa4SPaul Cercueil /* 2b5c23aa4SPaul Cercueil * Ingenic SoCs pinctrl driver 3b5c23aa4SPaul Cercueil * 4b5c23aa4SPaul Cercueil * Copyright (c) 2017 Paul Cercueil <paul@crapouillou.net> 5b5c23aa4SPaul Cercueil * 6b5c23aa4SPaul Cercueil * License terms: GNU General Public License (GPL) version 2 7b5c23aa4SPaul Cercueil */ 8b5c23aa4SPaul Cercueil 9b5c23aa4SPaul Cercueil #include <linux/compiler.h> 10b5c23aa4SPaul Cercueil #include <linux/gpio.h> 11b5c23aa4SPaul Cercueil #include <linux/interrupt.h> 12b5c23aa4SPaul Cercueil #include <linux/io.h> 13b5c23aa4SPaul Cercueil #include <linux/of_device.h> 14e72394e2SPaul Cercueil #include <linux/of_irq.h> 15b5c23aa4SPaul Cercueil #include <linux/of_platform.h> 16b5c23aa4SPaul Cercueil #include <linux/pinctrl/pinctrl.h> 17b5c23aa4SPaul Cercueil #include <linux/pinctrl/pinmux.h> 18b5c23aa4SPaul Cercueil #include <linux/pinctrl/pinconf.h> 19b5c23aa4SPaul Cercueil #include <linux/pinctrl/pinconf-generic.h> 20b5c23aa4SPaul Cercueil #include <linux/platform_device.h> 21b5c23aa4SPaul Cercueil #include <linux/regmap.h> 22b5c23aa4SPaul Cercueil #include <linux/slab.h> 23b5c23aa4SPaul Cercueil 24b5c23aa4SPaul Cercueil #include "core.h" 25b5c23aa4SPaul Cercueil #include "pinconf.h" 26b5c23aa4SPaul Cercueil #include "pinmux.h" 27b5c23aa4SPaul Cercueil 28e72394e2SPaul Cercueil #define GPIO_PIN 0x00 29e72394e2SPaul Cercueil #define GPIO_MSK 0x20 30e72394e2SPaul Cercueil 31b5c23aa4SPaul Cercueil #define JZ4740_GPIO_DATA 0x10 32b5c23aa4SPaul Cercueil #define JZ4740_GPIO_PULL_DIS 0x30 33b5c23aa4SPaul Cercueil #define JZ4740_GPIO_FUNC 0x40 34b5c23aa4SPaul Cercueil #define JZ4740_GPIO_SELECT 0x50 35b5c23aa4SPaul Cercueil #define JZ4740_GPIO_DIR 0x60 36b5c23aa4SPaul Cercueil #define JZ4740_GPIO_TRIG 0x70 37b5c23aa4SPaul Cercueil #define JZ4740_GPIO_FLAG 0x80 38b5c23aa4SPaul Cercueil 39b5c23aa4SPaul Cercueil #define JZ4770_GPIO_INT 0x10 40b5c23aa4SPaul Cercueil #define JZ4770_GPIO_PAT1 0x30 41b5c23aa4SPaul Cercueil #define JZ4770_GPIO_PAT0 0x40 42b5c23aa4SPaul Cercueil #define JZ4770_GPIO_FLAG 0x50 43b5c23aa4SPaul Cercueil #define JZ4770_GPIO_PEN 0x70 44b5c23aa4SPaul Cercueil 45b5c23aa4SPaul Cercueil #define REG_SET(x) ((x) + 0x4) 46b5c23aa4SPaul Cercueil #define REG_CLEAR(x) ((x) + 0x8) 47b5c23aa4SPaul Cercueil 48b5c23aa4SPaul Cercueil #define PINS_PER_GPIO_CHIP 32 49b5c23aa4SPaul Cercueil 50b5c23aa4SPaul Cercueil enum jz_version { 51b5c23aa4SPaul Cercueil ID_JZ4740, 52*f2a96765SPaul Cercueil ID_JZ4725B, 53b5c23aa4SPaul Cercueil ID_JZ4770, 54b5c23aa4SPaul Cercueil ID_JZ4780, 55b5c23aa4SPaul Cercueil }; 56b5c23aa4SPaul Cercueil 57b5c23aa4SPaul Cercueil struct ingenic_chip_info { 58b5c23aa4SPaul Cercueil unsigned int num_chips; 59b5c23aa4SPaul Cercueil 60b5c23aa4SPaul Cercueil const struct group_desc *groups; 61b5c23aa4SPaul Cercueil unsigned int num_groups; 62b5c23aa4SPaul Cercueil 63b5c23aa4SPaul Cercueil const struct function_desc *functions; 64b5c23aa4SPaul Cercueil unsigned int num_functions; 65b5c23aa4SPaul Cercueil 66b5c23aa4SPaul Cercueil const u32 *pull_ups, *pull_downs; 67b5c23aa4SPaul Cercueil }; 68b5c23aa4SPaul Cercueil 69b5c23aa4SPaul Cercueil struct ingenic_pinctrl { 70b5c23aa4SPaul Cercueil struct device *dev; 71b5c23aa4SPaul Cercueil struct regmap *map; 72b5c23aa4SPaul Cercueil struct pinctrl_dev *pctl; 73b5c23aa4SPaul Cercueil struct pinctrl_pin_desc *pdesc; 74b5c23aa4SPaul Cercueil enum jz_version version; 75b5c23aa4SPaul Cercueil 76b5c23aa4SPaul Cercueil const struct ingenic_chip_info *info; 77b5c23aa4SPaul Cercueil }; 78b5c23aa4SPaul Cercueil 79e72394e2SPaul Cercueil struct ingenic_gpio_chip { 80e72394e2SPaul Cercueil struct ingenic_pinctrl *jzpc; 81e72394e2SPaul Cercueil struct gpio_chip gc; 82e72394e2SPaul Cercueil struct irq_chip irq_chip; 83e72394e2SPaul Cercueil unsigned int irq, reg_base; 84e72394e2SPaul Cercueil }; 85e72394e2SPaul Cercueil 86b5c23aa4SPaul Cercueil static const u32 jz4740_pull_ups[4] = { 87b5c23aa4SPaul Cercueil 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 88b5c23aa4SPaul Cercueil }; 89b5c23aa4SPaul Cercueil 90b5c23aa4SPaul Cercueil static const u32 jz4740_pull_downs[4] = { 91b5c23aa4SPaul Cercueil 0x00000000, 0x00000000, 0x00000000, 0x00000000, 92b5c23aa4SPaul Cercueil }; 93b5c23aa4SPaul Cercueil 94b5c23aa4SPaul Cercueil static int jz4740_mmc_1bit_pins[] = { 0x69, 0x68, 0x6a, }; 95b5c23aa4SPaul Cercueil static int jz4740_mmc_4bit_pins[] = { 0x6b, 0x6c, 0x6d, }; 96b5c23aa4SPaul Cercueil static int jz4740_uart0_data_pins[] = { 0x7a, 0x79, }; 97b5c23aa4SPaul Cercueil static int jz4740_uart0_hwflow_pins[] = { 0x7e, 0x7f, }; 98b5c23aa4SPaul Cercueil static int jz4740_uart1_data_pins[] = { 0x7e, 0x7f, }; 99b5c23aa4SPaul Cercueil static int jz4740_lcd_8bit_pins[] = { 100b5c23aa4SPaul Cercueil 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x52, 0x53, 0x54, 101b5c23aa4SPaul Cercueil }; 102b5c23aa4SPaul Cercueil static int jz4740_lcd_16bit_pins[] = { 103b5c23aa4SPaul Cercueil 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x55, 104b5c23aa4SPaul Cercueil }; 105b5c23aa4SPaul Cercueil static int jz4740_lcd_18bit_pins[] = { 0x50, 0x51, }; 106b5c23aa4SPaul Cercueil static int jz4740_lcd_18bit_tft_pins[] = { 0x56, 0x57, 0x31, 0x32, }; 107b5c23aa4SPaul Cercueil static int jz4740_nand_cs1_pins[] = { 0x39, }; 108b5c23aa4SPaul Cercueil static int jz4740_nand_cs2_pins[] = { 0x3a, }; 109b5c23aa4SPaul Cercueil static int jz4740_nand_cs3_pins[] = { 0x3b, }; 110b5c23aa4SPaul Cercueil static int jz4740_nand_cs4_pins[] = { 0x3c, }; 111b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm0_pins[] = { 0x77, }; 112b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm1_pins[] = { 0x78, }; 113b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm2_pins[] = { 0x79, }; 114b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm3_pins[] = { 0x7a, }; 115b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm4_pins[] = { 0x7b, }; 116b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm5_pins[] = { 0x7c, }; 117b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm6_pins[] = { 0x7e, }; 118b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm7_pins[] = { 0x7f, }; 119b5c23aa4SPaul Cercueil 120b5c23aa4SPaul Cercueil static int jz4740_mmc_1bit_funcs[] = { 0, 0, 0, }; 121b5c23aa4SPaul Cercueil static int jz4740_mmc_4bit_funcs[] = { 0, 0, 0, }; 122b5c23aa4SPaul Cercueil static int jz4740_uart0_data_funcs[] = { 1, 1, }; 123b5c23aa4SPaul Cercueil static int jz4740_uart0_hwflow_funcs[] = { 1, 1, }; 124b5c23aa4SPaul Cercueil static int jz4740_uart1_data_funcs[] = { 2, 2, }; 125b5c23aa4SPaul Cercueil static int jz4740_lcd_8bit_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; 126b5c23aa4SPaul Cercueil static int jz4740_lcd_16bit_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, }; 127b5c23aa4SPaul Cercueil static int jz4740_lcd_18bit_funcs[] = { 0, 0, }; 128b5c23aa4SPaul Cercueil static int jz4740_lcd_18bit_tft_funcs[] = { 0, 0, 0, 0, }; 129b5c23aa4SPaul Cercueil static int jz4740_nand_cs1_funcs[] = { 0, }; 130b5c23aa4SPaul Cercueil static int jz4740_nand_cs2_funcs[] = { 0, }; 131b5c23aa4SPaul Cercueil static int jz4740_nand_cs3_funcs[] = { 0, }; 132b5c23aa4SPaul Cercueil static int jz4740_nand_cs4_funcs[] = { 0, }; 133b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm0_funcs[] = { 0, }; 134b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm1_funcs[] = { 0, }; 135b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm2_funcs[] = { 0, }; 136b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm3_funcs[] = { 0, }; 137b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm4_funcs[] = { 0, }; 138b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm5_funcs[] = { 0, }; 139b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm6_funcs[] = { 0, }; 140b5c23aa4SPaul Cercueil static int jz4740_pwm_pwm7_funcs[] = { 0, }; 141b5c23aa4SPaul Cercueil 142b5c23aa4SPaul Cercueil #define INGENIC_PIN_GROUP(name, id) \ 143b5c23aa4SPaul Cercueil { \ 144b5c23aa4SPaul Cercueil name, \ 145b5c23aa4SPaul Cercueil id##_pins, \ 146b5c23aa4SPaul Cercueil ARRAY_SIZE(id##_pins), \ 147b5c23aa4SPaul Cercueil id##_funcs, \ 148b5c23aa4SPaul Cercueil } 149b5c23aa4SPaul Cercueil 150b5c23aa4SPaul Cercueil static const struct group_desc jz4740_groups[] = { 151b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("mmc-1bit", jz4740_mmc_1bit), 152b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("mmc-4bit", jz4740_mmc_4bit), 153b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("uart0-data", jz4740_uart0_data), 154b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("uart0-hwflow", jz4740_uart0_hwflow), 155b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("uart1-data", jz4740_uart1_data), 156b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("lcd-8bit", jz4740_lcd_8bit), 157b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("lcd-16bit", jz4740_lcd_16bit), 158b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("lcd-18bit", jz4740_lcd_18bit), 159b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("lcd-18bit-tft", jz4740_lcd_18bit_tft), 160b5c23aa4SPaul Cercueil { "lcd-no-pins", }, 161b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("nand-cs1", jz4740_nand_cs1), 162b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("nand-cs2", jz4740_nand_cs2), 163b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("nand-cs3", jz4740_nand_cs3), 164b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("nand-cs4", jz4740_nand_cs4), 165b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("pwm0", jz4740_pwm_pwm0), 166b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("pwm1", jz4740_pwm_pwm1), 167b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("pwm2", jz4740_pwm_pwm2), 168b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("pwm3", jz4740_pwm_pwm3), 169b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("pwm4", jz4740_pwm_pwm4), 170b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("pwm5", jz4740_pwm_pwm5), 171b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("pwm6", jz4740_pwm_pwm6), 172b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("pwm7", jz4740_pwm_pwm7), 173b5c23aa4SPaul Cercueil }; 174b5c23aa4SPaul Cercueil 175b5c23aa4SPaul Cercueil static const char *jz4740_mmc_groups[] = { "mmc-1bit", "mmc-4bit", }; 176b5c23aa4SPaul Cercueil static const char *jz4740_uart0_groups[] = { "uart0-data", "uart0-hwflow", }; 177b5c23aa4SPaul Cercueil static const char *jz4740_uart1_groups[] = { "uart1-data", }; 178b5c23aa4SPaul Cercueil static const char *jz4740_lcd_groups[] = { 179b5c23aa4SPaul Cercueil "lcd-8bit", "lcd-16bit", "lcd-18bit", "lcd-18bit-tft", "lcd-no-pins", 180b5c23aa4SPaul Cercueil }; 181b5c23aa4SPaul Cercueil static const char *jz4740_nand_groups[] = { 182b5c23aa4SPaul Cercueil "nand-cs1", "nand-cs2", "nand-cs3", "nand-cs4", 183b5c23aa4SPaul Cercueil }; 184b5c23aa4SPaul Cercueil static const char *jz4740_pwm0_groups[] = { "pwm0", }; 185b5c23aa4SPaul Cercueil static const char *jz4740_pwm1_groups[] = { "pwm1", }; 186b5c23aa4SPaul Cercueil static const char *jz4740_pwm2_groups[] = { "pwm2", }; 187b5c23aa4SPaul Cercueil static const char *jz4740_pwm3_groups[] = { "pwm3", }; 188b5c23aa4SPaul Cercueil static const char *jz4740_pwm4_groups[] = { "pwm4", }; 189b5c23aa4SPaul Cercueil static const char *jz4740_pwm5_groups[] = { "pwm5", }; 190b5c23aa4SPaul Cercueil static const char *jz4740_pwm6_groups[] = { "pwm6", }; 191b5c23aa4SPaul Cercueil static const char *jz4740_pwm7_groups[] = { "pwm7", }; 192b5c23aa4SPaul Cercueil 193b5c23aa4SPaul Cercueil static const struct function_desc jz4740_functions[] = { 194b5c23aa4SPaul Cercueil { "mmc", jz4740_mmc_groups, ARRAY_SIZE(jz4740_mmc_groups), }, 195b5c23aa4SPaul Cercueil { "uart0", jz4740_uart0_groups, ARRAY_SIZE(jz4740_uart0_groups), }, 196b5c23aa4SPaul Cercueil { "uart1", jz4740_uart1_groups, ARRAY_SIZE(jz4740_uart1_groups), }, 197b5c23aa4SPaul Cercueil { "lcd", jz4740_lcd_groups, ARRAY_SIZE(jz4740_lcd_groups), }, 198b5c23aa4SPaul Cercueil { "nand", jz4740_nand_groups, ARRAY_SIZE(jz4740_nand_groups), }, 199b5c23aa4SPaul Cercueil { "pwm0", jz4740_pwm0_groups, ARRAY_SIZE(jz4740_pwm0_groups), }, 200b5c23aa4SPaul Cercueil { "pwm1", jz4740_pwm1_groups, ARRAY_SIZE(jz4740_pwm1_groups), }, 201b5c23aa4SPaul Cercueil { "pwm2", jz4740_pwm2_groups, ARRAY_SIZE(jz4740_pwm2_groups), }, 202b5c23aa4SPaul Cercueil { "pwm3", jz4740_pwm3_groups, ARRAY_SIZE(jz4740_pwm3_groups), }, 203b5c23aa4SPaul Cercueil { "pwm4", jz4740_pwm4_groups, ARRAY_SIZE(jz4740_pwm4_groups), }, 204b5c23aa4SPaul Cercueil { "pwm5", jz4740_pwm5_groups, ARRAY_SIZE(jz4740_pwm5_groups), }, 205b5c23aa4SPaul Cercueil { "pwm6", jz4740_pwm6_groups, ARRAY_SIZE(jz4740_pwm6_groups), }, 206b5c23aa4SPaul Cercueil { "pwm7", jz4740_pwm7_groups, ARRAY_SIZE(jz4740_pwm7_groups), }, 207b5c23aa4SPaul Cercueil }; 208b5c23aa4SPaul Cercueil 209b5c23aa4SPaul Cercueil static const struct ingenic_chip_info jz4740_chip_info = { 210b5c23aa4SPaul Cercueil .num_chips = 4, 211b5c23aa4SPaul Cercueil .groups = jz4740_groups, 212b5c23aa4SPaul Cercueil .num_groups = ARRAY_SIZE(jz4740_groups), 213b5c23aa4SPaul Cercueil .functions = jz4740_functions, 214b5c23aa4SPaul Cercueil .num_functions = ARRAY_SIZE(jz4740_functions), 215b5c23aa4SPaul Cercueil .pull_ups = jz4740_pull_ups, 216b5c23aa4SPaul Cercueil .pull_downs = jz4740_pull_downs, 217b5c23aa4SPaul Cercueil }; 218b5c23aa4SPaul Cercueil 219*f2a96765SPaul Cercueil static int jz4725b_mmc0_1bit_pins[] = { 0x48, 0x49, 0x5c, }; 220*f2a96765SPaul Cercueil static int jz4725b_mmc0_4bit_pins[] = { 0x5d, 0x5b, 0x56, }; 221*f2a96765SPaul Cercueil static int jz4725b_mmc1_1bit_pins[] = { 0x7a, 0x7b, 0x7c, }; 222*f2a96765SPaul Cercueil static int jz4725b_mmc1_4bit_pins[] = { 0x7d, 0x7e, 0x7f, }; 223*f2a96765SPaul Cercueil static int jz4725b_uart_data_pins[] = { 0x4c, 0x4d, }; 224*f2a96765SPaul Cercueil static int jz4725b_nand_cs1_pins[] = { 0x55, }; 225*f2a96765SPaul Cercueil static int jz4725b_nand_cs2_pins[] = { 0x56, }; 226*f2a96765SPaul Cercueil static int jz4725b_nand_cs3_pins[] = { 0x57, }; 227*f2a96765SPaul Cercueil static int jz4725b_nand_cs4_pins[] = { 0x58, }; 228*f2a96765SPaul Cercueil static int jz4725b_nand_cle_ale_pins[] = { 0x48, 0x49 }; 229*f2a96765SPaul Cercueil static int jz4725b_nand_fre_fwe_pins[] = { 0x5c, 0x5d }; 230*f2a96765SPaul Cercueil static int jz4725b_pwm_pwm0_pins[] = { 0x4a, }; 231*f2a96765SPaul Cercueil static int jz4725b_pwm_pwm1_pins[] = { 0x4b, }; 232*f2a96765SPaul Cercueil static int jz4725b_pwm_pwm2_pins[] = { 0x4c, }; 233*f2a96765SPaul Cercueil static int jz4725b_pwm_pwm3_pins[] = { 0x4d, }; 234*f2a96765SPaul Cercueil static int jz4725b_pwm_pwm4_pins[] = { 0x4e, }; 235*f2a96765SPaul Cercueil static int jz4725b_pwm_pwm5_pins[] = { 0x4f, }; 236*f2a96765SPaul Cercueil 237*f2a96765SPaul Cercueil static int jz4725b_mmc0_1bit_funcs[] = { 1, 1, 1, }; 238*f2a96765SPaul Cercueil static int jz4725b_mmc0_4bit_funcs[] = { 1, 0, 1, }; 239*f2a96765SPaul Cercueil static int jz4725b_mmc1_1bit_funcs[] = { 0, 0, 0, }; 240*f2a96765SPaul Cercueil static int jz4725b_mmc1_4bit_funcs[] = { 0, 0, 0, }; 241*f2a96765SPaul Cercueil static int jz4725b_uart_data_funcs[] = { 1, 1, }; 242*f2a96765SPaul Cercueil static int jz4725b_nand_cs1_funcs[] = { 0, }; 243*f2a96765SPaul Cercueil static int jz4725b_nand_cs2_funcs[] = { 0, }; 244*f2a96765SPaul Cercueil static int jz4725b_nand_cs3_funcs[] = { 0, }; 245*f2a96765SPaul Cercueil static int jz4725b_nand_cs4_funcs[] = { 0, }; 246*f2a96765SPaul Cercueil static int jz4725b_nand_cle_ale_funcs[] = { 0, 0, }; 247*f2a96765SPaul Cercueil static int jz4725b_nand_fre_fwe_funcs[] = { 0, 0, }; 248*f2a96765SPaul Cercueil static int jz4725b_pwm_pwm0_funcs[] = { 0, }; 249*f2a96765SPaul Cercueil static int jz4725b_pwm_pwm1_funcs[] = { 0, }; 250*f2a96765SPaul Cercueil static int jz4725b_pwm_pwm2_funcs[] = { 0, }; 251*f2a96765SPaul Cercueil static int jz4725b_pwm_pwm3_funcs[] = { 0, }; 252*f2a96765SPaul Cercueil static int jz4725b_pwm_pwm4_funcs[] = { 0, }; 253*f2a96765SPaul Cercueil static int jz4725b_pwm_pwm5_funcs[] = { 0, }; 254*f2a96765SPaul Cercueil 255*f2a96765SPaul Cercueil static const struct group_desc jz4725b_groups[] = { 256*f2a96765SPaul Cercueil INGENIC_PIN_GROUP("mmc0-1bit", jz4725b_mmc0_1bit), 257*f2a96765SPaul Cercueil INGENIC_PIN_GROUP("mmc0-4bit", jz4725b_mmc0_4bit), 258*f2a96765SPaul Cercueil INGENIC_PIN_GROUP("mmc1-1bit", jz4725b_mmc1_1bit), 259*f2a96765SPaul Cercueil INGENIC_PIN_GROUP("mmc1-4bit", jz4725b_mmc1_4bit), 260*f2a96765SPaul Cercueil INGENIC_PIN_GROUP("uart-data", jz4725b_uart_data), 261*f2a96765SPaul Cercueil INGENIC_PIN_GROUP("nand-cs1", jz4725b_nand_cs1), 262*f2a96765SPaul Cercueil INGENIC_PIN_GROUP("nand-cs2", jz4725b_nand_cs2), 263*f2a96765SPaul Cercueil INGENIC_PIN_GROUP("nand-cs3", jz4725b_nand_cs3), 264*f2a96765SPaul Cercueil INGENIC_PIN_GROUP("nand-cs4", jz4725b_nand_cs4), 265*f2a96765SPaul Cercueil INGENIC_PIN_GROUP("nand-cle-ale", jz4725b_nand_cle_ale), 266*f2a96765SPaul Cercueil INGENIC_PIN_GROUP("nand-fre-fwe", jz4725b_nand_fre_fwe), 267*f2a96765SPaul Cercueil INGENIC_PIN_GROUP("pwm0", jz4725b_pwm_pwm0), 268*f2a96765SPaul Cercueil INGENIC_PIN_GROUP("pwm1", jz4725b_pwm_pwm1), 269*f2a96765SPaul Cercueil INGENIC_PIN_GROUP("pwm2", jz4725b_pwm_pwm2), 270*f2a96765SPaul Cercueil INGENIC_PIN_GROUP("pwm3", jz4725b_pwm_pwm3), 271*f2a96765SPaul Cercueil INGENIC_PIN_GROUP("pwm4", jz4725b_pwm_pwm4), 272*f2a96765SPaul Cercueil INGENIC_PIN_GROUP("pwm5", jz4725b_pwm_pwm5), 273*f2a96765SPaul Cercueil }; 274*f2a96765SPaul Cercueil 275*f2a96765SPaul Cercueil static const char *jz4725b_mmc0_groups[] = { "mmc0-1bit", "mmc0-4bit", }; 276*f2a96765SPaul Cercueil static const char *jz4725b_mmc1_groups[] = { "mmc1-1bit", "mmc1-4bit", }; 277*f2a96765SPaul Cercueil static const char *jz4725b_uart_groups[] = { "uart-data", }; 278*f2a96765SPaul Cercueil static const char *jz4725b_nand_groups[] = { 279*f2a96765SPaul Cercueil "nand-cs1", "nand-cs2", "nand-cs3", "nand-cs4", 280*f2a96765SPaul Cercueil "nand-cle-ale", "nand-fre-fwe", 281*f2a96765SPaul Cercueil }; 282*f2a96765SPaul Cercueil static const char *jz4725b_pwm0_groups[] = { "pwm0", }; 283*f2a96765SPaul Cercueil static const char *jz4725b_pwm1_groups[] = { "pwm1", }; 284*f2a96765SPaul Cercueil static const char *jz4725b_pwm2_groups[] = { "pwm2", }; 285*f2a96765SPaul Cercueil static const char *jz4725b_pwm3_groups[] = { "pwm3", }; 286*f2a96765SPaul Cercueil static const char *jz4725b_pwm4_groups[] = { "pwm4", }; 287*f2a96765SPaul Cercueil static const char *jz4725b_pwm5_groups[] = { "pwm5", }; 288*f2a96765SPaul Cercueil 289*f2a96765SPaul Cercueil static const struct function_desc jz4725b_functions[] = { 290*f2a96765SPaul Cercueil { "mmc0", jz4725b_mmc0_groups, ARRAY_SIZE(jz4725b_mmc0_groups), }, 291*f2a96765SPaul Cercueil { "mmc1", jz4725b_mmc1_groups, ARRAY_SIZE(jz4725b_mmc1_groups), }, 292*f2a96765SPaul Cercueil { "uart", jz4725b_uart_groups, ARRAY_SIZE(jz4725b_uart_groups), }, 293*f2a96765SPaul Cercueil { "nand", jz4725b_nand_groups, ARRAY_SIZE(jz4725b_nand_groups), }, 294*f2a96765SPaul Cercueil { "pwm0", jz4725b_pwm0_groups, ARRAY_SIZE(jz4725b_pwm0_groups), }, 295*f2a96765SPaul Cercueil { "pwm1", jz4725b_pwm1_groups, ARRAY_SIZE(jz4725b_pwm1_groups), }, 296*f2a96765SPaul Cercueil { "pwm2", jz4725b_pwm2_groups, ARRAY_SIZE(jz4725b_pwm2_groups), }, 297*f2a96765SPaul Cercueil { "pwm3", jz4725b_pwm3_groups, ARRAY_SIZE(jz4725b_pwm3_groups), }, 298*f2a96765SPaul Cercueil { "pwm4", jz4725b_pwm4_groups, ARRAY_SIZE(jz4725b_pwm4_groups), }, 299*f2a96765SPaul Cercueil { "pwm5", jz4725b_pwm5_groups, ARRAY_SIZE(jz4725b_pwm5_groups), }, 300*f2a96765SPaul Cercueil }; 301*f2a96765SPaul Cercueil 302*f2a96765SPaul Cercueil static const struct ingenic_chip_info jz4725b_chip_info = { 303*f2a96765SPaul Cercueil .num_chips = 4, 304*f2a96765SPaul Cercueil .groups = jz4725b_groups, 305*f2a96765SPaul Cercueil .num_groups = ARRAY_SIZE(jz4725b_groups), 306*f2a96765SPaul Cercueil .functions = jz4725b_functions, 307*f2a96765SPaul Cercueil .num_functions = ARRAY_SIZE(jz4725b_functions), 308*f2a96765SPaul Cercueil .pull_ups = jz4740_pull_ups, 309*f2a96765SPaul Cercueil .pull_downs = jz4740_pull_downs, 310*f2a96765SPaul Cercueil }; 311*f2a96765SPaul Cercueil 312b5c23aa4SPaul Cercueil static const u32 jz4770_pull_ups[6] = { 313b5c23aa4SPaul Cercueil 0x3fffffff, 0xfff0030c, 0xffffffff, 0xffff4fff, 0xfffffb7c, 0xffa7f00f, 314b5c23aa4SPaul Cercueil }; 315b5c23aa4SPaul Cercueil 316b5c23aa4SPaul Cercueil static const u32 jz4770_pull_downs[6] = { 317b5c23aa4SPaul Cercueil 0x00000000, 0x000f0c03, 0x00000000, 0x0000b000, 0x00000483, 0x00580ff0, 318b5c23aa4SPaul Cercueil }; 319b5c23aa4SPaul Cercueil 320b5c23aa4SPaul Cercueil static int jz4770_uart0_data_pins[] = { 0xa0, 0xa3, }; 321b5c23aa4SPaul Cercueil static int jz4770_uart0_hwflow_pins[] = { 0xa1, 0xa2, }; 322b5c23aa4SPaul Cercueil static int jz4770_uart1_data_pins[] = { 0x7a, 0x7c, }; 323b5c23aa4SPaul Cercueil static int jz4770_uart1_hwflow_pins[] = { 0x7b, 0x7d, }; 324b5c23aa4SPaul Cercueil static int jz4770_uart2_data_pins[] = { 0x66, 0x67, }; 325b5c23aa4SPaul Cercueil static int jz4770_uart2_hwflow_pins[] = { 0x65, 0x64, }; 326b5c23aa4SPaul Cercueil static int jz4770_uart3_data_pins[] = { 0x6c, 0x85, }; 327b5c23aa4SPaul Cercueil static int jz4770_uart3_hwflow_pins[] = { 0x88, 0x89, }; 328b5c23aa4SPaul Cercueil static int jz4770_uart4_data_pins[] = { 0x54, 0x4a, }; 329b5c23aa4SPaul Cercueil static int jz4770_mmc0_8bit_a_pins[] = { 0x04, 0x05, 0x06, 0x07, 0x18, }; 330b5c23aa4SPaul Cercueil static int jz4770_mmc0_4bit_a_pins[] = { 0x15, 0x16, 0x17, }; 331b5c23aa4SPaul Cercueil static int jz4770_mmc0_1bit_a_pins[] = { 0x12, 0x13, 0x14, }; 332b5c23aa4SPaul Cercueil static int jz4770_mmc0_4bit_e_pins[] = { 0x95, 0x96, 0x97, }; 333b5c23aa4SPaul Cercueil static int jz4770_mmc0_1bit_e_pins[] = { 0x9c, 0x9d, 0x94, }; 334b5c23aa4SPaul Cercueil static int jz4770_mmc1_4bit_d_pins[] = { 0x75, 0x76, 0x77, }; 335b5c23aa4SPaul Cercueil static int jz4770_mmc1_1bit_d_pins[] = { 0x78, 0x79, 0x74, }; 336b5c23aa4SPaul Cercueil static int jz4770_mmc1_4bit_e_pins[] = { 0x95, 0x96, 0x97, }; 337b5c23aa4SPaul Cercueil static int jz4770_mmc1_1bit_e_pins[] = { 0x9c, 0x9d, 0x94, }; 338b5c23aa4SPaul Cercueil static int jz4770_nemc_data_pins[] = { 339b5c23aa4SPaul Cercueil 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 340b5c23aa4SPaul Cercueil }; 341b5c23aa4SPaul Cercueil static int jz4770_nemc_cle_ale_pins[] = { 0x20, 0x21, }; 342b5c23aa4SPaul Cercueil static int jz4770_nemc_addr_pins[] = { 0x22, 0x23, 0x24, 0x25, }; 343b5c23aa4SPaul Cercueil static int jz4770_nemc_rd_we_pins[] = { 0x10, 0x11, }; 344b5c23aa4SPaul Cercueil static int jz4770_nemc_frd_fwe_pins[] = { 0x12, 0x13, }; 345b5c23aa4SPaul Cercueil static int jz4770_nemc_cs1_pins[] = { 0x15, }; 346b5c23aa4SPaul Cercueil static int jz4770_nemc_cs2_pins[] = { 0x16, }; 347b5c23aa4SPaul Cercueil static int jz4770_nemc_cs3_pins[] = { 0x17, }; 348b5c23aa4SPaul Cercueil static int jz4770_nemc_cs4_pins[] = { 0x18, }; 349b5c23aa4SPaul Cercueil static int jz4770_nemc_cs5_pins[] = { 0x19, }; 350b5c23aa4SPaul Cercueil static int jz4770_nemc_cs6_pins[] = { 0x1a, }; 351b5c23aa4SPaul Cercueil static int jz4770_i2c0_pins[] = { 0x6e, 0x6f, }; 352b5c23aa4SPaul Cercueil static int jz4770_i2c1_pins[] = { 0x8e, 0x8f, }; 353b5c23aa4SPaul Cercueil static int jz4770_i2c2_pins[] = { 0xb0, 0xb1, }; 354b5c23aa4SPaul Cercueil static int jz4770_i2c3_pins[] = { 0x6a, 0x6b, }; 355b5c23aa4SPaul Cercueil static int jz4770_i2c4_e_pins[] = { 0x8c, 0x8d, }; 356b5c23aa4SPaul Cercueil static int jz4770_i2c4_f_pins[] = { 0xb9, 0xb8, }; 357b5c23aa4SPaul Cercueil static int jz4770_cim_pins[] = { 358b5c23aa4SPaul Cercueil 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 359b5c23aa4SPaul Cercueil }; 360b5c23aa4SPaul Cercueil static int jz4770_lcd_32bit_pins[] = { 361b5c23aa4SPaul Cercueil 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 362b5c23aa4SPaul Cercueil 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 363b5c23aa4SPaul Cercueil 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 364b5c23aa4SPaul Cercueil 0x58, 0x59, 0x51, 365b5c23aa4SPaul Cercueil }; 366b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm0_pins[] = { 0x80, }; 367b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm1_pins[] = { 0x81, }; 368b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm2_pins[] = { 0x82, }; 369b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm3_pins[] = { 0x83, }; 370b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm4_pins[] = { 0x84, }; 371b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm5_pins[] = { 0x85, }; 372b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm6_pins[] = { 0x6a, }; 373b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm7_pins[] = { 0x6b, }; 374b5c23aa4SPaul Cercueil 375b5c23aa4SPaul Cercueil static int jz4770_uart0_data_funcs[] = { 0, 0, }; 376b5c23aa4SPaul Cercueil static int jz4770_uart0_hwflow_funcs[] = { 0, 0, }; 377b5c23aa4SPaul Cercueil static int jz4770_uart1_data_funcs[] = { 0, 0, }; 378b5c23aa4SPaul Cercueil static int jz4770_uart1_hwflow_funcs[] = { 0, 0, }; 379b5c23aa4SPaul Cercueil static int jz4770_uart2_data_funcs[] = { 1, 1, }; 380b5c23aa4SPaul Cercueil static int jz4770_uart2_hwflow_funcs[] = { 1, 1, }; 381b5c23aa4SPaul Cercueil static int jz4770_uart3_data_funcs[] = { 0, 1, }; 382b5c23aa4SPaul Cercueil static int jz4770_uart3_hwflow_funcs[] = { 0, 0, }; 383b5c23aa4SPaul Cercueil static int jz4770_uart4_data_funcs[] = { 2, 2, }; 384b5c23aa4SPaul Cercueil static int jz4770_mmc0_8bit_a_funcs[] = { 1, 1, 1, 1, 1, }; 385b5c23aa4SPaul Cercueil static int jz4770_mmc0_4bit_a_funcs[] = { 1, 1, 1, }; 386b5c23aa4SPaul Cercueil static int jz4770_mmc0_1bit_a_funcs[] = { 1, 1, 0, }; 387b5c23aa4SPaul Cercueil static int jz4770_mmc0_4bit_e_funcs[] = { 0, 0, 0, }; 388b5c23aa4SPaul Cercueil static int jz4770_mmc0_1bit_e_funcs[] = { 0, 0, 0, }; 389b5c23aa4SPaul Cercueil static int jz4770_mmc1_4bit_d_funcs[] = { 0, 0, 0, }; 390b5c23aa4SPaul Cercueil static int jz4770_mmc1_1bit_d_funcs[] = { 0, 0, 0, }; 391b5c23aa4SPaul Cercueil static int jz4770_mmc1_4bit_e_funcs[] = { 1, 1, 1, }; 392b5c23aa4SPaul Cercueil static int jz4770_mmc1_1bit_e_funcs[] = { 1, 1, 1, }; 393b5c23aa4SPaul Cercueil static int jz4770_nemc_data_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, }; 394b5c23aa4SPaul Cercueil static int jz4770_nemc_cle_ale_funcs[] = { 0, 0, }; 395b5c23aa4SPaul Cercueil static int jz4770_nemc_addr_funcs[] = { 0, 0, 0, 0, }; 396b5c23aa4SPaul Cercueil static int jz4770_nemc_rd_we_funcs[] = { 0, 0, }; 397b5c23aa4SPaul Cercueil static int jz4770_nemc_frd_fwe_funcs[] = { 0, 0, }; 398b5c23aa4SPaul Cercueil static int jz4770_nemc_cs1_funcs[] = { 0, }; 399b5c23aa4SPaul Cercueil static int jz4770_nemc_cs2_funcs[] = { 0, }; 400b5c23aa4SPaul Cercueil static int jz4770_nemc_cs3_funcs[] = { 0, }; 401b5c23aa4SPaul Cercueil static int jz4770_nemc_cs4_funcs[] = { 0, }; 402b5c23aa4SPaul Cercueil static int jz4770_nemc_cs5_funcs[] = { 0, }; 403b5c23aa4SPaul Cercueil static int jz4770_nemc_cs6_funcs[] = { 0, }; 404b5c23aa4SPaul Cercueil static int jz4770_i2c0_funcs[] = { 0, 0, }; 405b5c23aa4SPaul Cercueil static int jz4770_i2c1_funcs[] = { 0, 0, }; 406b5c23aa4SPaul Cercueil static int jz4770_i2c2_funcs[] = { 2, 2, }; 407b5c23aa4SPaul Cercueil static int jz4770_i2c3_funcs[] = { 1, 1, }; 408b5c23aa4SPaul Cercueil static int jz4770_i2c4_e_funcs[] = { 1, 1, }; 409b5c23aa4SPaul Cercueil static int jz4770_i2c4_f_funcs[] = { 1, 1, }; 410b5c23aa4SPaul Cercueil static int jz4770_cim_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; 411b5c23aa4SPaul Cercueil static int jz4770_lcd_32bit_funcs[] = { 412b5c23aa4SPaul Cercueil 0, 0, 0, 0, 0, 0, 0, 0, 413b5c23aa4SPaul Cercueil 0, 0, 0, 0, 0, 0, 0, 0, 414b5c23aa4SPaul Cercueil 0, 0, 0, 415b5c23aa4SPaul Cercueil }; 416b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm0_funcs[] = { 0, }; 417b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm1_funcs[] = { 0, }; 418b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm2_funcs[] = { 0, }; 419b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm3_funcs[] = { 0, }; 420b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm4_funcs[] = { 0, }; 421b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm5_funcs[] = { 0, }; 422b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm6_funcs[] = { 0, }; 423b5c23aa4SPaul Cercueil static int jz4770_pwm_pwm7_funcs[] = { 0, }; 424b5c23aa4SPaul Cercueil 425b5c23aa4SPaul Cercueil static const struct group_desc jz4770_groups[] = { 426b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("uart0-data", jz4770_uart0_data), 427b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("uart0-hwflow", jz4770_uart0_hwflow), 428b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("uart1-data", jz4770_uart1_data), 429b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("uart1-hwflow", jz4770_uart1_hwflow), 430b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("uart2-data", jz4770_uart2_data), 431b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("uart2-hwflow", jz4770_uart2_hwflow), 432b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("uart3-data", jz4770_uart3_data), 433b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("uart3-hwflow", jz4770_uart3_hwflow), 434b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("uart4-data", jz4770_uart4_data), 435b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("mmc0-8bit-a", jz4770_mmc0_8bit_a), 436b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("mmc0-4bit-a", jz4770_mmc0_4bit_a), 437b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("mmc0-1bit-a", jz4770_mmc0_1bit_a), 438b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("mmc0-4bit-e", jz4770_mmc0_4bit_e), 439b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("mmc0-1bit-e", jz4770_mmc0_1bit_e), 440b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("mmc1-4bit-d", jz4770_mmc1_4bit_d), 441b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("mmc1-1bit-d", jz4770_mmc1_1bit_d), 442b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("mmc1-4bit-e", jz4770_mmc1_4bit_e), 443b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("mmc1-1bit-e", jz4770_mmc1_1bit_e), 444b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("nemc-data", jz4770_nemc_data), 445b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("nemc-cle-ale", jz4770_nemc_cle_ale), 446b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("nemc-addr", jz4770_nemc_addr), 447b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("nemc-rd-we", jz4770_nemc_rd_we), 448b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("nemc-frd-fwe", jz4770_nemc_frd_fwe), 449b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("nemc-cs1", jz4770_nemc_cs1), 450b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("nemc-cs2", jz4770_nemc_cs2), 451b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("nemc-cs3", jz4770_nemc_cs3), 452b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("nemc-cs4", jz4770_nemc_cs4), 453b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("nemc-cs5", jz4770_nemc_cs5), 454b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("nemc-cs6", jz4770_nemc_cs6), 455b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("i2c0-data", jz4770_i2c0), 456b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("i2c1-data", jz4770_i2c1), 457b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("i2c2-data", jz4770_i2c2), 458b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("i2c3-data", jz4770_i2c3), 459b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("i2c4-data-e", jz4770_i2c4_e), 460b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("i2c4-data-f", jz4770_i2c4_f), 461b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("cim-data", jz4770_cim), 462b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("lcd-32bit", jz4770_lcd_32bit), 463b5c23aa4SPaul Cercueil { "lcd-no-pins", }, 464b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("pwm0", jz4770_pwm_pwm0), 465b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("pwm1", jz4770_pwm_pwm1), 466b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("pwm2", jz4770_pwm_pwm2), 467b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("pwm3", jz4770_pwm_pwm3), 468b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("pwm4", jz4770_pwm_pwm4), 469b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("pwm5", jz4770_pwm_pwm5), 470b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("pwm6", jz4770_pwm_pwm6), 471b5c23aa4SPaul Cercueil INGENIC_PIN_GROUP("pwm7", jz4770_pwm_pwm7), 472b5c23aa4SPaul Cercueil }; 473b5c23aa4SPaul Cercueil 474b5c23aa4SPaul Cercueil static const char *jz4770_uart0_groups[] = { "uart0-data", "uart0-hwflow", }; 475b5c23aa4SPaul Cercueil static const char *jz4770_uart1_groups[] = { "uart1-data", "uart1-hwflow", }; 476b5c23aa4SPaul Cercueil static const char *jz4770_uart2_groups[] = { "uart2-data", "uart2-hwflow", }; 477b5c23aa4SPaul Cercueil static const char *jz4770_uart3_groups[] = { "uart3-data", "uart3-hwflow", }; 478b5c23aa4SPaul Cercueil static const char *jz4770_uart4_groups[] = { "uart4-data", }; 479b5c23aa4SPaul Cercueil static const char *jz4770_mmc0_groups[] = { 480b5c23aa4SPaul Cercueil "mmc0-8bit-a", "mmc0-4bit-a", "mmc0-1bit-a", 481b5c23aa4SPaul Cercueil "mmc0-1bit-e", "mmc0-4bit-e", 482b5c23aa4SPaul Cercueil }; 483b5c23aa4SPaul Cercueil static const char *jz4770_mmc1_groups[] = { 484b5c23aa4SPaul Cercueil "mmc1-1bit-d", "mmc1-4bit-d", "mmc1-1bit-e", "mmc1-4bit-e", 485b5c23aa4SPaul Cercueil }; 486b5c23aa4SPaul Cercueil static const char *jz4770_nemc_groups[] = { 487b5c23aa4SPaul Cercueil "nemc-data", "nemc-cle-ale", "nemc-addr", "nemc-rd-we", "nemc-frd-fwe", 488b5c23aa4SPaul Cercueil }; 489b5c23aa4SPaul Cercueil static const char *jz4770_cs1_groups[] = { "nemc-cs1", }; 490b5c23aa4SPaul Cercueil static const char *jz4770_cs6_groups[] = { "nemc-cs6", }; 491b5c23aa4SPaul Cercueil static const char *jz4770_i2c0_groups[] = { "i2c0-data", }; 492b5c23aa4SPaul Cercueil static const char *jz4770_i2c1_groups[] = { "i2c1-data", }; 493b5c23aa4SPaul Cercueil static const char *jz4770_i2c2_groups[] = { "i2c2-data", }; 494b5c23aa4SPaul Cercueil static const char *jz4770_i2c3_groups[] = { "i2c3-data", }; 495b5c23aa4SPaul Cercueil static const char *jz4770_i2c4_groups[] = { "i2c4-data-e", "i2c4-data-f", }; 496b5c23aa4SPaul Cercueil static const char *jz4770_cim_groups[] = { "cim-data", }; 497b5c23aa4SPaul Cercueil static const char *jz4770_lcd_groups[] = { "lcd-32bit", "lcd-no-pins", }; 498b5c23aa4SPaul Cercueil static const char *jz4770_pwm0_groups[] = { "pwm0", }; 499b5c23aa4SPaul Cercueil static const char *jz4770_pwm1_groups[] = { "pwm1", }; 500b5c23aa4SPaul Cercueil static const char *jz4770_pwm2_groups[] = { "pwm2", }; 501b5c23aa4SPaul Cercueil static const char *jz4770_pwm3_groups[] = { "pwm3", }; 502b5c23aa4SPaul Cercueil static const char *jz4770_pwm4_groups[] = { "pwm4", }; 503b5c23aa4SPaul Cercueil static const char *jz4770_pwm5_groups[] = { "pwm5", }; 504b5c23aa4SPaul Cercueil static const char *jz4770_pwm6_groups[] = { "pwm6", }; 505b5c23aa4SPaul Cercueil static const char *jz4770_pwm7_groups[] = { "pwm7", }; 506b5c23aa4SPaul Cercueil 507b5c23aa4SPaul Cercueil static const struct function_desc jz4770_functions[] = { 508b5c23aa4SPaul Cercueil { "uart0", jz4770_uart0_groups, ARRAY_SIZE(jz4770_uart0_groups), }, 509b5c23aa4SPaul Cercueil { "uart1", jz4770_uart1_groups, ARRAY_SIZE(jz4770_uart1_groups), }, 510b5c23aa4SPaul Cercueil { "uart2", jz4770_uart2_groups, ARRAY_SIZE(jz4770_uart2_groups), }, 511b5c23aa4SPaul Cercueil { "uart3", jz4770_uart3_groups, ARRAY_SIZE(jz4770_uart3_groups), }, 512b5c23aa4SPaul Cercueil { "uart4", jz4770_uart4_groups, ARRAY_SIZE(jz4770_uart4_groups), }, 513b5c23aa4SPaul Cercueil { "mmc0", jz4770_mmc0_groups, ARRAY_SIZE(jz4770_mmc0_groups), }, 514b5c23aa4SPaul Cercueil { "mmc1", jz4770_mmc1_groups, ARRAY_SIZE(jz4770_mmc1_groups), }, 515b5c23aa4SPaul Cercueil { "nemc", jz4770_nemc_groups, ARRAY_SIZE(jz4770_nemc_groups), }, 516b5c23aa4SPaul Cercueil { "nemc-cs1", jz4770_cs1_groups, ARRAY_SIZE(jz4770_cs1_groups), }, 517b5c23aa4SPaul Cercueil { "nemc-cs6", jz4770_cs6_groups, ARRAY_SIZE(jz4770_cs6_groups), }, 518b5c23aa4SPaul Cercueil { "i2c0", jz4770_i2c0_groups, ARRAY_SIZE(jz4770_i2c0_groups), }, 519b5c23aa4SPaul Cercueil { "i2c1", jz4770_i2c1_groups, ARRAY_SIZE(jz4770_i2c1_groups), }, 520b5c23aa4SPaul Cercueil { "i2c2", jz4770_i2c2_groups, ARRAY_SIZE(jz4770_i2c2_groups), }, 521b5c23aa4SPaul Cercueil { "i2c3", jz4770_i2c3_groups, ARRAY_SIZE(jz4770_i2c3_groups), }, 522b5c23aa4SPaul Cercueil { "i2c4", jz4770_i2c4_groups, ARRAY_SIZE(jz4770_i2c4_groups), }, 523b5c23aa4SPaul Cercueil { "cim", jz4770_cim_groups, ARRAY_SIZE(jz4770_cim_groups), }, 524b5c23aa4SPaul Cercueil { "lcd", jz4770_lcd_groups, ARRAY_SIZE(jz4770_lcd_groups), }, 525b5c23aa4SPaul Cercueil { "pwm0", jz4770_pwm0_groups, ARRAY_SIZE(jz4770_pwm0_groups), }, 526b5c23aa4SPaul Cercueil { "pwm1", jz4770_pwm1_groups, ARRAY_SIZE(jz4770_pwm1_groups), }, 527b5c23aa4SPaul Cercueil { "pwm2", jz4770_pwm2_groups, ARRAY_SIZE(jz4770_pwm2_groups), }, 528b5c23aa4SPaul Cercueil { "pwm3", jz4770_pwm3_groups, ARRAY_SIZE(jz4770_pwm3_groups), }, 529b5c23aa4SPaul Cercueil { "pwm4", jz4770_pwm4_groups, ARRAY_SIZE(jz4770_pwm4_groups), }, 530b5c23aa4SPaul Cercueil { "pwm5", jz4770_pwm5_groups, ARRAY_SIZE(jz4770_pwm5_groups), }, 531b5c23aa4SPaul Cercueil { "pwm6", jz4770_pwm6_groups, ARRAY_SIZE(jz4770_pwm6_groups), }, 532b5c23aa4SPaul Cercueil { "pwm7", jz4770_pwm7_groups, ARRAY_SIZE(jz4770_pwm7_groups), }, 533b5c23aa4SPaul Cercueil }; 534b5c23aa4SPaul Cercueil 535b5c23aa4SPaul Cercueil static const struct ingenic_chip_info jz4770_chip_info = { 536b5c23aa4SPaul Cercueil .num_chips = 6, 537b5c23aa4SPaul Cercueil .groups = jz4770_groups, 538b5c23aa4SPaul Cercueil .num_groups = ARRAY_SIZE(jz4770_groups), 539b5c23aa4SPaul Cercueil .functions = jz4770_functions, 540b5c23aa4SPaul Cercueil .num_functions = ARRAY_SIZE(jz4770_functions), 541b5c23aa4SPaul Cercueil .pull_ups = jz4770_pull_ups, 542b5c23aa4SPaul Cercueil .pull_downs = jz4770_pull_downs, 543b5c23aa4SPaul Cercueil }; 544b5c23aa4SPaul Cercueil 545e72394e2SPaul Cercueil static u32 gpio_ingenic_read_reg(struct ingenic_gpio_chip *jzgc, u8 reg) 546e72394e2SPaul Cercueil { 547e72394e2SPaul Cercueil unsigned int val; 548e72394e2SPaul Cercueil 549e72394e2SPaul Cercueil regmap_read(jzgc->jzpc->map, jzgc->reg_base + reg, &val); 550e72394e2SPaul Cercueil 551e72394e2SPaul Cercueil return (u32) val; 552e72394e2SPaul Cercueil } 553e72394e2SPaul Cercueil 554e72394e2SPaul Cercueil static void gpio_ingenic_set_bit(struct ingenic_gpio_chip *jzgc, 555e72394e2SPaul Cercueil u8 reg, u8 offset, bool set) 556e72394e2SPaul Cercueil { 557e72394e2SPaul Cercueil if (set) 558e72394e2SPaul Cercueil reg = REG_SET(reg); 559e72394e2SPaul Cercueil else 560e72394e2SPaul Cercueil reg = REG_CLEAR(reg); 561e72394e2SPaul Cercueil 562e72394e2SPaul Cercueil regmap_write(jzgc->jzpc->map, jzgc->reg_base + reg, BIT(offset)); 563e72394e2SPaul Cercueil } 564e72394e2SPaul Cercueil 565e72394e2SPaul Cercueil static inline bool ingenic_gpio_get_value(struct ingenic_gpio_chip *jzgc, 566e72394e2SPaul Cercueil u8 offset) 567e72394e2SPaul Cercueil { 568e72394e2SPaul Cercueil unsigned int val = gpio_ingenic_read_reg(jzgc, GPIO_PIN); 569e72394e2SPaul Cercueil 570e72394e2SPaul Cercueil return !!(val & BIT(offset)); 571e72394e2SPaul Cercueil } 572e72394e2SPaul Cercueil 573e72394e2SPaul Cercueil static void ingenic_gpio_set_value(struct ingenic_gpio_chip *jzgc, 574e72394e2SPaul Cercueil u8 offset, int value) 575e72394e2SPaul Cercueil { 576e72394e2SPaul Cercueil if (jzgc->jzpc->version >= ID_JZ4770) 577e72394e2SPaul Cercueil gpio_ingenic_set_bit(jzgc, JZ4770_GPIO_PAT0, offset, !!value); 578e72394e2SPaul Cercueil else 579e72394e2SPaul Cercueil gpio_ingenic_set_bit(jzgc, JZ4740_GPIO_DATA, offset, !!value); 580e72394e2SPaul Cercueil } 581e72394e2SPaul Cercueil 582e72394e2SPaul Cercueil static void irq_set_type(struct ingenic_gpio_chip *jzgc, 583e72394e2SPaul Cercueil u8 offset, unsigned int type) 584e72394e2SPaul Cercueil { 585e72394e2SPaul Cercueil u8 reg1, reg2; 586e72394e2SPaul Cercueil 587e72394e2SPaul Cercueil if (jzgc->jzpc->version >= ID_JZ4770) { 588e72394e2SPaul Cercueil reg1 = JZ4770_GPIO_PAT1; 589e72394e2SPaul Cercueil reg2 = JZ4770_GPIO_PAT0; 590e72394e2SPaul Cercueil } else { 591e72394e2SPaul Cercueil reg1 = JZ4740_GPIO_TRIG; 592e72394e2SPaul Cercueil reg2 = JZ4740_GPIO_DIR; 593e72394e2SPaul Cercueil } 594e72394e2SPaul Cercueil 595e72394e2SPaul Cercueil switch (type) { 596e72394e2SPaul Cercueil case IRQ_TYPE_EDGE_RISING: 597e72394e2SPaul Cercueil gpio_ingenic_set_bit(jzgc, reg2, offset, true); 598e72394e2SPaul Cercueil gpio_ingenic_set_bit(jzgc, reg1, offset, true); 599e72394e2SPaul Cercueil break; 600e72394e2SPaul Cercueil case IRQ_TYPE_EDGE_FALLING: 601e72394e2SPaul Cercueil gpio_ingenic_set_bit(jzgc, reg2, offset, false); 602e72394e2SPaul Cercueil gpio_ingenic_set_bit(jzgc, reg1, offset, true); 603e72394e2SPaul Cercueil break; 604e72394e2SPaul Cercueil case IRQ_TYPE_LEVEL_HIGH: 605e72394e2SPaul Cercueil gpio_ingenic_set_bit(jzgc, reg2, offset, true); 606e72394e2SPaul Cercueil gpio_ingenic_set_bit(jzgc, reg1, offset, false); 607e72394e2SPaul Cercueil break; 608e72394e2SPaul Cercueil case IRQ_TYPE_LEVEL_LOW: 609e72394e2SPaul Cercueil default: 610e72394e2SPaul Cercueil gpio_ingenic_set_bit(jzgc, reg2, offset, false); 611e72394e2SPaul Cercueil gpio_ingenic_set_bit(jzgc, reg1, offset, false); 612e72394e2SPaul Cercueil break; 613e72394e2SPaul Cercueil } 614e72394e2SPaul Cercueil } 615e72394e2SPaul Cercueil 616e72394e2SPaul Cercueil static void ingenic_gpio_irq_mask(struct irq_data *irqd) 617e72394e2SPaul Cercueil { 618e72394e2SPaul Cercueil struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); 619e72394e2SPaul Cercueil struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc); 620e72394e2SPaul Cercueil 621e72394e2SPaul Cercueil gpio_ingenic_set_bit(jzgc, GPIO_MSK, irqd->hwirq, true); 622e72394e2SPaul Cercueil } 623e72394e2SPaul Cercueil 624e72394e2SPaul Cercueil static void ingenic_gpio_irq_unmask(struct irq_data *irqd) 625e72394e2SPaul Cercueil { 626e72394e2SPaul Cercueil struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); 627e72394e2SPaul Cercueil struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc); 628e72394e2SPaul Cercueil 629e72394e2SPaul Cercueil gpio_ingenic_set_bit(jzgc, GPIO_MSK, irqd->hwirq, false); 630e72394e2SPaul Cercueil } 631e72394e2SPaul Cercueil 632e72394e2SPaul Cercueil static void ingenic_gpio_irq_enable(struct irq_data *irqd) 633e72394e2SPaul Cercueil { 634e72394e2SPaul Cercueil struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); 635e72394e2SPaul Cercueil struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc); 636e72394e2SPaul Cercueil int irq = irqd->hwirq; 637e72394e2SPaul Cercueil 638e72394e2SPaul Cercueil if (jzgc->jzpc->version >= ID_JZ4770) 639e72394e2SPaul Cercueil gpio_ingenic_set_bit(jzgc, JZ4770_GPIO_INT, irq, true); 640e72394e2SPaul Cercueil else 641e72394e2SPaul Cercueil gpio_ingenic_set_bit(jzgc, JZ4740_GPIO_SELECT, irq, true); 642e72394e2SPaul Cercueil 643e72394e2SPaul Cercueil ingenic_gpio_irq_unmask(irqd); 644e72394e2SPaul Cercueil } 645e72394e2SPaul Cercueil 646e72394e2SPaul Cercueil static void ingenic_gpio_irq_disable(struct irq_data *irqd) 647e72394e2SPaul Cercueil { 648e72394e2SPaul Cercueil struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); 649e72394e2SPaul Cercueil struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc); 650e72394e2SPaul Cercueil int irq = irqd->hwirq; 651e72394e2SPaul Cercueil 652e72394e2SPaul Cercueil ingenic_gpio_irq_mask(irqd); 653e72394e2SPaul Cercueil 654e72394e2SPaul Cercueil if (jzgc->jzpc->version >= ID_JZ4770) 655e72394e2SPaul Cercueil gpio_ingenic_set_bit(jzgc, JZ4770_GPIO_INT, irq, false); 656e72394e2SPaul Cercueil else 657e72394e2SPaul Cercueil gpio_ingenic_set_bit(jzgc, JZ4740_GPIO_SELECT, irq, false); 658e72394e2SPaul Cercueil } 659e72394e2SPaul Cercueil 660e72394e2SPaul Cercueil static void ingenic_gpio_irq_ack(struct irq_data *irqd) 661e72394e2SPaul Cercueil { 662e72394e2SPaul Cercueil struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); 663e72394e2SPaul Cercueil struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc); 664e72394e2SPaul Cercueil int irq = irqd->hwirq; 665e72394e2SPaul Cercueil bool high; 666e72394e2SPaul Cercueil 667e72394e2SPaul Cercueil if (irqd_get_trigger_type(irqd) == IRQ_TYPE_EDGE_BOTH) { 668e72394e2SPaul Cercueil /* 669e72394e2SPaul Cercueil * Switch to an interrupt for the opposite edge to the one that 670e72394e2SPaul Cercueil * triggered the interrupt being ACKed. 671e72394e2SPaul Cercueil */ 672e72394e2SPaul Cercueil high = ingenic_gpio_get_value(jzgc, irq); 673e72394e2SPaul Cercueil if (high) 674e72394e2SPaul Cercueil irq_set_type(jzgc, irq, IRQ_TYPE_EDGE_FALLING); 675e72394e2SPaul Cercueil else 676e72394e2SPaul Cercueil irq_set_type(jzgc, irq, IRQ_TYPE_EDGE_RISING); 677e72394e2SPaul Cercueil } 678e72394e2SPaul Cercueil 679e72394e2SPaul Cercueil if (jzgc->jzpc->version >= ID_JZ4770) 680e72394e2SPaul Cercueil gpio_ingenic_set_bit(jzgc, JZ4770_GPIO_FLAG, irq, false); 681e72394e2SPaul Cercueil else 682e72394e2SPaul Cercueil gpio_ingenic_set_bit(jzgc, JZ4740_GPIO_DATA, irq, true); 683e72394e2SPaul Cercueil } 684e72394e2SPaul Cercueil 685e72394e2SPaul Cercueil static int ingenic_gpio_irq_set_type(struct irq_data *irqd, unsigned int type) 686e72394e2SPaul Cercueil { 687e72394e2SPaul Cercueil struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); 688e72394e2SPaul Cercueil struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc); 689e72394e2SPaul Cercueil 690e72394e2SPaul Cercueil switch (type) { 691e72394e2SPaul Cercueil case IRQ_TYPE_EDGE_BOTH: 692e72394e2SPaul Cercueil case IRQ_TYPE_EDGE_RISING: 693e72394e2SPaul Cercueil case IRQ_TYPE_EDGE_FALLING: 694e72394e2SPaul Cercueil irq_set_handler_locked(irqd, handle_edge_irq); 695e72394e2SPaul Cercueil break; 696e72394e2SPaul Cercueil case IRQ_TYPE_LEVEL_HIGH: 697e72394e2SPaul Cercueil case IRQ_TYPE_LEVEL_LOW: 698e72394e2SPaul Cercueil irq_set_handler_locked(irqd, handle_level_irq); 699e72394e2SPaul Cercueil break; 700e72394e2SPaul Cercueil default: 701e72394e2SPaul Cercueil irq_set_handler_locked(irqd, handle_bad_irq); 702e72394e2SPaul Cercueil } 703e72394e2SPaul Cercueil 704e72394e2SPaul Cercueil if (type == IRQ_TYPE_EDGE_BOTH) { 705e72394e2SPaul Cercueil /* 706e72394e2SPaul Cercueil * The hardware does not support interrupts on both edges. The 707e72394e2SPaul Cercueil * best we can do is to set up a single-edge interrupt and then 708e72394e2SPaul Cercueil * switch to the opposing edge when ACKing the interrupt. 709e72394e2SPaul Cercueil */ 710e72394e2SPaul Cercueil bool high = ingenic_gpio_get_value(jzgc, irqd->hwirq); 711e72394e2SPaul Cercueil 712e72394e2SPaul Cercueil type = high ? IRQ_TYPE_EDGE_FALLING : IRQ_TYPE_EDGE_RISING; 713e72394e2SPaul Cercueil } 714e72394e2SPaul Cercueil 715e72394e2SPaul Cercueil irq_set_type(jzgc, irqd->hwirq, type); 716e72394e2SPaul Cercueil return 0; 717e72394e2SPaul Cercueil } 718e72394e2SPaul Cercueil 719e72394e2SPaul Cercueil static int ingenic_gpio_irq_set_wake(struct irq_data *irqd, unsigned int on) 720e72394e2SPaul Cercueil { 721e72394e2SPaul Cercueil struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); 722e72394e2SPaul Cercueil struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc); 723e72394e2SPaul Cercueil 724e72394e2SPaul Cercueil return irq_set_irq_wake(jzgc->irq, on); 725e72394e2SPaul Cercueil } 726e72394e2SPaul Cercueil 727e72394e2SPaul Cercueil static void ingenic_gpio_irq_handler(struct irq_desc *desc) 728e72394e2SPaul Cercueil { 729e72394e2SPaul Cercueil struct gpio_chip *gc = irq_desc_get_handler_data(desc); 730e72394e2SPaul Cercueil struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc); 731e72394e2SPaul Cercueil struct irq_chip *irq_chip = irq_data_get_irq_chip(&desc->irq_data); 732e72394e2SPaul Cercueil unsigned long flag, i; 733e72394e2SPaul Cercueil 734e72394e2SPaul Cercueil chained_irq_enter(irq_chip, desc); 735e72394e2SPaul Cercueil 736e72394e2SPaul Cercueil if (jzgc->jzpc->version >= ID_JZ4770) 737e72394e2SPaul Cercueil flag = gpio_ingenic_read_reg(jzgc, JZ4770_GPIO_FLAG); 738e72394e2SPaul Cercueil else 739e72394e2SPaul Cercueil flag = gpio_ingenic_read_reg(jzgc, JZ4740_GPIO_FLAG); 740e72394e2SPaul Cercueil 741e72394e2SPaul Cercueil for_each_set_bit(i, &flag, 32) 742e72394e2SPaul Cercueil generic_handle_irq(irq_linear_revmap(gc->irq.domain, i)); 743e72394e2SPaul Cercueil chained_irq_exit(irq_chip, desc); 744e72394e2SPaul Cercueil } 745e72394e2SPaul Cercueil 746e72394e2SPaul Cercueil static void ingenic_gpio_set(struct gpio_chip *gc, 747e72394e2SPaul Cercueil unsigned int offset, int value) 748e72394e2SPaul Cercueil { 749e72394e2SPaul Cercueil struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc); 750e72394e2SPaul Cercueil 751e72394e2SPaul Cercueil ingenic_gpio_set_value(jzgc, offset, value); 752e72394e2SPaul Cercueil } 753e72394e2SPaul Cercueil 754e72394e2SPaul Cercueil static int ingenic_gpio_get(struct gpio_chip *gc, unsigned int offset) 755e72394e2SPaul Cercueil { 756e72394e2SPaul Cercueil struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc); 757e72394e2SPaul Cercueil 758e72394e2SPaul Cercueil return (int) ingenic_gpio_get_value(jzgc, offset); 759e72394e2SPaul Cercueil } 760e72394e2SPaul Cercueil 761e72394e2SPaul Cercueil static int ingenic_gpio_direction_input(struct gpio_chip *gc, 762e72394e2SPaul Cercueil unsigned int offset) 763e72394e2SPaul Cercueil { 764e72394e2SPaul Cercueil return pinctrl_gpio_direction_input(gc->base + offset); 765e72394e2SPaul Cercueil } 766e72394e2SPaul Cercueil 767e72394e2SPaul Cercueil static int ingenic_gpio_direction_output(struct gpio_chip *gc, 768e72394e2SPaul Cercueil unsigned int offset, int value) 769e72394e2SPaul Cercueil { 770e72394e2SPaul Cercueil ingenic_gpio_set(gc, offset, value); 771e72394e2SPaul Cercueil return pinctrl_gpio_direction_output(gc->base + offset); 772e72394e2SPaul Cercueil } 773e72394e2SPaul Cercueil 774b5c23aa4SPaul Cercueil static inline void ingenic_config_pin(struct ingenic_pinctrl *jzpc, 775b5c23aa4SPaul Cercueil unsigned int pin, u8 reg, bool set) 776b5c23aa4SPaul Cercueil { 777b5c23aa4SPaul Cercueil unsigned int idx = pin % PINS_PER_GPIO_CHIP; 778b5c23aa4SPaul Cercueil unsigned int offt = pin / PINS_PER_GPIO_CHIP; 779b5c23aa4SPaul Cercueil 780b5c23aa4SPaul Cercueil regmap_write(jzpc->map, offt * 0x100 + 781b5c23aa4SPaul Cercueil (set ? REG_SET(reg) : REG_CLEAR(reg)), BIT(idx)); 782b5c23aa4SPaul Cercueil } 783b5c23aa4SPaul Cercueil 784b5c23aa4SPaul Cercueil static inline bool ingenic_get_pin_config(struct ingenic_pinctrl *jzpc, 785b5c23aa4SPaul Cercueil unsigned int pin, u8 reg) 786b5c23aa4SPaul Cercueil { 787b5c23aa4SPaul Cercueil unsigned int idx = pin % PINS_PER_GPIO_CHIP; 788b5c23aa4SPaul Cercueil unsigned int offt = pin / PINS_PER_GPIO_CHIP; 789b5c23aa4SPaul Cercueil unsigned int val; 790b5c23aa4SPaul Cercueil 791b5c23aa4SPaul Cercueil regmap_read(jzpc->map, offt * 0x100 + reg, &val); 792b5c23aa4SPaul Cercueil 793b5c23aa4SPaul Cercueil return val & BIT(idx); 794b5c23aa4SPaul Cercueil } 795b5c23aa4SPaul Cercueil 796ebd66514SPaul Cercueil static int ingenic_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) 797ebd66514SPaul Cercueil { 798ebd66514SPaul Cercueil struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc); 799ebd66514SPaul Cercueil struct ingenic_pinctrl *jzpc = jzgc->jzpc; 800ebd66514SPaul Cercueil unsigned int pin = gc->base + offset; 801ebd66514SPaul Cercueil 802ebd66514SPaul Cercueil if (jzpc->version >= ID_JZ4770) 803ebd66514SPaul Cercueil return ingenic_get_pin_config(jzpc, pin, JZ4770_GPIO_PAT1); 804ebd66514SPaul Cercueil 805ebd66514SPaul Cercueil if (ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_SELECT)) 806ebd66514SPaul Cercueil return true; 807ebd66514SPaul Cercueil 808ebd66514SPaul Cercueil return !ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_DIR); 809ebd66514SPaul Cercueil } 810ebd66514SPaul Cercueil 8115bf7b849SJulia Lawall static const struct pinctrl_ops ingenic_pctlops = { 812b5c23aa4SPaul Cercueil .get_groups_count = pinctrl_generic_get_group_count, 813b5c23aa4SPaul Cercueil .get_group_name = pinctrl_generic_get_group_name, 814b5c23aa4SPaul Cercueil .get_group_pins = pinctrl_generic_get_group_pins, 815b5c23aa4SPaul Cercueil .dt_node_to_map = pinconf_generic_dt_node_to_map_all, 816b5c23aa4SPaul Cercueil .dt_free_map = pinconf_generic_dt_free_map, 817b5c23aa4SPaul Cercueil }; 818b5c23aa4SPaul Cercueil 819b5c23aa4SPaul Cercueil static int ingenic_pinmux_set_pin_fn(struct ingenic_pinctrl *jzpc, 820b5c23aa4SPaul Cercueil int pin, int func) 821b5c23aa4SPaul Cercueil { 822b5c23aa4SPaul Cercueil unsigned int idx = pin % PINS_PER_GPIO_CHIP; 823b5c23aa4SPaul Cercueil unsigned int offt = pin / PINS_PER_GPIO_CHIP; 824b5c23aa4SPaul Cercueil 825b5c23aa4SPaul Cercueil dev_dbg(jzpc->dev, "set pin P%c%u to function %u\n", 826b5c23aa4SPaul Cercueil 'A' + offt, idx, func); 827b5c23aa4SPaul Cercueil 828b5c23aa4SPaul Cercueil if (jzpc->version >= ID_JZ4770) { 829b5c23aa4SPaul Cercueil ingenic_config_pin(jzpc, pin, JZ4770_GPIO_INT, false); 830e72394e2SPaul Cercueil ingenic_config_pin(jzpc, pin, GPIO_MSK, false); 831b5c23aa4SPaul Cercueil ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PAT1, func & 0x2); 832b5c23aa4SPaul Cercueil ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PAT0, func & 0x1); 833b5c23aa4SPaul Cercueil } else { 834b5c23aa4SPaul Cercueil ingenic_config_pin(jzpc, pin, JZ4740_GPIO_FUNC, true); 835b5c23aa4SPaul Cercueil ingenic_config_pin(jzpc, pin, JZ4740_GPIO_TRIG, func & 0x2); 836b5c23aa4SPaul Cercueil ingenic_config_pin(jzpc, pin, JZ4740_GPIO_SELECT, func > 0); 837b5c23aa4SPaul Cercueil } 838b5c23aa4SPaul Cercueil 839b5c23aa4SPaul Cercueil return 0; 840b5c23aa4SPaul Cercueil } 841b5c23aa4SPaul Cercueil 842b5c23aa4SPaul Cercueil static int ingenic_pinmux_set_mux(struct pinctrl_dev *pctldev, 843b5c23aa4SPaul Cercueil unsigned int selector, unsigned int group) 844b5c23aa4SPaul Cercueil { 845b5c23aa4SPaul Cercueil struct ingenic_pinctrl *jzpc = pinctrl_dev_get_drvdata(pctldev); 846b5c23aa4SPaul Cercueil struct function_desc *func; 847b5c23aa4SPaul Cercueil struct group_desc *grp; 848b5c23aa4SPaul Cercueil unsigned int i; 849b5c23aa4SPaul Cercueil 850b5c23aa4SPaul Cercueil func = pinmux_generic_get_function(pctldev, selector); 851b5c23aa4SPaul Cercueil if (!func) 852b5c23aa4SPaul Cercueil return -EINVAL; 853b5c23aa4SPaul Cercueil 854b5c23aa4SPaul Cercueil grp = pinctrl_generic_get_group(pctldev, group); 855b5c23aa4SPaul Cercueil if (!grp) 856b5c23aa4SPaul Cercueil return -EINVAL; 857b5c23aa4SPaul Cercueil 858b5c23aa4SPaul Cercueil dev_dbg(pctldev->dev, "enable function %s group %s\n", 859b5c23aa4SPaul Cercueil func->name, grp->name); 860b5c23aa4SPaul Cercueil 861b5c23aa4SPaul Cercueil for (i = 0; i < grp->num_pins; i++) { 862b5c23aa4SPaul Cercueil int *pin_modes = grp->data; 863b5c23aa4SPaul Cercueil 864b5c23aa4SPaul Cercueil ingenic_pinmux_set_pin_fn(jzpc, grp->pins[i], pin_modes[i]); 865b5c23aa4SPaul Cercueil } 866b5c23aa4SPaul Cercueil 867b5c23aa4SPaul Cercueil return 0; 868b5c23aa4SPaul Cercueil } 869b5c23aa4SPaul Cercueil 870b5c23aa4SPaul Cercueil static int ingenic_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev, 871b5c23aa4SPaul Cercueil struct pinctrl_gpio_range *range, 872b5c23aa4SPaul Cercueil unsigned int pin, bool input) 873b5c23aa4SPaul Cercueil { 874b5c23aa4SPaul Cercueil struct ingenic_pinctrl *jzpc = pinctrl_dev_get_drvdata(pctldev); 875b5c23aa4SPaul Cercueil unsigned int idx = pin % PINS_PER_GPIO_CHIP; 876b5c23aa4SPaul Cercueil unsigned int offt = pin / PINS_PER_GPIO_CHIP; 877b5c23aa4SPaul Cercueil 878b5c23aa4SPaul Cercueil dev_dbg(pctldev->dev, "set pin P%c%u to %sput\n", 879b5c23aa4SPaul Cercueil 'A' + offt, idx, input ? "in" : "out"); 880b5c23aa4SPaul Cercueil 881b5c23aa4SPaul Cercueil if (jzpc->version >= ID_JZ4770) { 882b5c23aa4SPaul Cercueil ingenic_config_pin(jzpc, pin, JZ4770_GPIO_INT, false); 883e72394e2SPaul Cercueil ingenic_config_pin(jzpc, pin, GPIO_MSK, true); 884b5c23aa4SPaul Cercueil ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PAT1, input); 885b5c23aa4SPaul Cercueil } else { 886b5c23aa4SPaul Cercueil ingenic_config_pin(jzpc, pin, JZ4740_GPIO_SELECT, false); 8870084a786SPaul Cercueil ingenic_config_pin(jzpc, pin, JZ4740_GPIO_DIR, !input); 888b5c23aa4SPaul Cercueil ingenic_config_pin(jzpc, pin, JZ4740_GPIO_FUNC, false); 889b5c23aa4SPaul Cercueil } 890b5c23aa4SPaul Cercueil 891b5c23aa4SPaul Cercueil return 0; 892b5c23aa4SPaul Cercueil } 893b5c23aa4SPaul Cercueil 8945bf7b849SJulia Lawall static const struct pinmux_ops ingenic_pmxops = { 895b5c23aa4SPaul Cercueil .get_functions_count = pinmux_generic_get_function_count, 896b5c23aa4SPaul Cercueil .get_function_name = pinmux_generic_get_function_name, 897b5c23aa4SPaul Cercueil .get_function_groups = pinmux_generic_get_function_groups, 898b5c23aa4SPaul Cercueil .set_mux = ingenic_pinmux_set_mux, 899b5c23aa4SPaul Cercueil .gpio_set_direction = ingenic_pinmux_gpio_set_direction, 900b5c23aa4SPaul Cercueil }; 901b5c23aa4SPaul Cercueil 902b5c23aa4SPaul Cercueil static int ingenic_pinconf_get(struct pinctrl_dev *pctldev, 903b5c23aa4SPaul Cercueil unsigned int pin, unsigned long *config) 904b5c23aa4SPaul Cercueil { 905b5c23aa4SPaul Cercueil struct ingenic_pinctrl *jzpc = pinctrl_dev_get_drvdata(pctldev); 906b5c23aa4SPaul Cercueil enum pin_config_param param = pinconf_to_config_param(*config); 907b5c23aa4SPaul Cercueil unsigned int idx = pin % PINS_PER_GPIO_CHIP; 908b5c23aa4SPaul Cercueil unsigned int offt = pin / PINS_PER_GPIO_CHIP; 909b5c23aa4SPaul Cercueil bool pull; 910b5c23aa4SPaul Cercueil 911b5c23aa4SPaul Cercueil if (jzpc->version >= ID_JZ4770) 912b5c23aa4SPaul Cercueil pull = !ingenic_get_pin_config(jzpc, pin, JZ4770_GPIO_PEN); 913b5c23aa4SPaul Cercueil else 914b5c23aa4SPaul Cercueil pull = !ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_PULL_DIS); 915b5c23aa4SPaul Cercueil 916b5c23aa4SPaul Cercueil switch (param) { 917b5c23aa4SPaul Cercueil case PIN_CONFIG_BIAS_DISABLE: 918b5c23aa4SPaul Cercueil if (pull) 919b5c23aa4SPaul Cercueil return -EINVAL; 920b5c23aa4SPaul Cercueil break; 921b5c23aa4SPaul Cercueil 922b5c23aa4SPaul Cercueil case PIN_CONFIG_BIAS_PULL_UP: 923b5c23aa4SPaul Cercueil if (!pull || !(jzpc->info->pull_ups[offt] & BIT(idx))) 924b5c23aa4SPaul Cercueil return -EINVAL; 925b5c23aa4SPaul Cercueil break; 926b5c23aa4SPaul Cercueil 927b5c23aa4SPaul Cercueil case PIN_CONFIG_BIAS_PULL_DOWN: 928b5c23aa4SPaul Cercueil if (!pull || !(jzpc->info->pull_downs[offt] & BIT(idx))) 929b5c23aa4SPaul Cercueil return -EINVAL; 930b5c23aa4SPaul Cercueil break; 931b5c23aa4SPaul Cercueil 932b5c23aa4SPaul Cercueil default: 933b5c23aa4SPaul Cercueil return -ENOTSUPP; 934b5c23aa4SPaul Cercueil } 935b5c23aa4SPaul Cercueil 936b5c23aa4SPaul Cercueil *config = pinconf_to_config_packed(param, 1); 937b5c23aa4SPaul Cercueil return 0; 938b5c23aa4SPaul Cercueil } 939b5c23aa4SPaul Cercueil 940b5c23aa4SPaul Cercueil static void ingenic_set_bias(struct ingenic_pinctrl *jzpc, 941b5c23aa4SPaul Cercueil unsigned int pin, bool enabled) 942b5c23aa4SPaul Cercueil { 943b5c23aa4SPaul Cercueil if (jzpc->version >= ID_JZ4770) 944b5c23aa4SPaul Cercueil ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PEN, !enabled); 945b5c23aa4SPaul Cercueil else 946b5c23aa4SPaul Cercueil ingenic_config_pin(jzpc, pin, JZ4740_GPIO_PULL_DIS, !enabled); 947b5c23aa4SPaul Cercueil } 948b5c23aa4SPaul Cercueil 949b5c23aa4SPaul Cercueil static int ingenic_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, 950b5c23aa4SPaul Cercueil unsigned long *configs, unsigned int num_configs) 951b5c23aa4SPaul Cercueil { 952b5c23aa4SPaul Cercueil struct ingenic_pinctrl *jzpc = pinctrl_dev_get_drvdata(pctldev); 953b5c23aa4SPaul Cercueil unsigned int idx = pin % PINS_PER_GPIO_CHIP; 954b5c23aa4SPaul Cercueil unsigned int offt = pin / PINS_PER_GPIO_CHIP; 955b5c23aa4SPaul Cercueil unsigned int cfg; 956b5c23aa4SPaul Cercueil 957b5c23aa4SPaul Cercueil for (cfg = 0; cfg < num_configs; cfg++) { 958b5c23aa4SPaul Cercueil switch (pinconf_to_config_param(configs[cfg])) { 959b5c23aa4SPaul Cercueil case PIN_CONFIG_BIAS_DISABLE: 960b5c23aa4SPaul Cercueil case PIN_CONFIG_BIAS_PULL_UP: 961b5c23aa4SPaul Cercueil case PIN_CONFIG_BIAS_PULL_DOWN: 962b5c23aa4SPaul Cercueil continue; 963b5c23aa4SPaul Cercueil default: 964b5c23aa4SPaul Cercueil return -ENOTSUPP; 965b5c23aa4SPaul Cercueil } 966b5c23aa4SPaul Cercueil } 967b5c23aa4SPaul Cercueil 968b5c23aa4SPaul Cercueil for (cfg = 0; cfg < num_configs; cfg++) { 969b5c23aa4SPaul Cercueil switch (pinconf_to_config_param(configs[cfg])) { 970b5c23aa4SPaul Cercueil case PIN_CONFIG_BIAS_DISABLE: 971b5c23aa4SPaul Cercueil dev_dbg(jzpc->dev, "disable pull-over for pin P%c%u\n", 972b5c23aa4SPaul Cercueil 'A' + offt, idx); 973b5c23aa4SPaul Cercueil ingenic_set_bias(jzpc, pin, false); 974b5c23aa4SPaul Cercueil break; 975b5c23aa4SPaul Cercueil 976b5c23aa4SPaul Cercueil case PIN_CONFIG_BIAS_PULL_UP: 977b5c23aa4SPaul Cercueil if (!(jzpc->info->pull_ups[offt] & BIT(idx))) 978b5c23aa4SPaul Cercueil return -EINVAL; 979b5c23aa4SPaul Cercueil dev_dbg(jzpc->dev, "set pull-up for pin P%c%u\n", 980b5c23aa4SPaul Cercueil 'A' + offt, idx); 981b5c23aa4SPaul Cercueil ingenic_set_bias(jzpc, pin, true); 982b5c23aa4SPaul Cercueil break; 983b5c23aa4SPaul Cercueil 984b5c23aa4SPaul Cercueil case PIN_CONFIG_BIAS_PULL_DOWN: 985b5c23aa4SPaul Cercueil if (!(jzpc->info->pull_downs[offt] & BIT(idx))) 986b5c23aa4SPaul Cercueil return -EINVAL; 987b5c23aa4SPaul Cercueil dev_dbg(jzpc->dev, "set pull-down for pin P%c%u\n", 988b5c23aa4SPaul Cercueil 'A' + offt, idx); 989b5c23aa4SPaul Cercueil ingenic_set_bias(jzpc, pin, true); 990b5c23aa4SPaul Cercueil break; 991b5c23aa4SPaul Cercueil 992b5c23aa4SPaul Cercueil default: 993b5c23aa4SPaul Cercueil unreachable(); 994b5c23aa4SPaul Cercueil } 995b5c23aa4SPaul Cercueil } 996b5c23aa4SPaul Cercueil 997b5c23aa4SPaul Cercueil return 0; 998b5c23aa4SPaul Cercueil } 999b5c23aa4SPaul Cercueil 1000b5c23aa4SPaul Cercueil static int ingenic_pinconf_group_get(struct pinctrl_dev *pctldev, 1001b5c23aa4SPaul Cercueil unsigned int group, unsigned long *config) 1002b5c23aa4SPaul Cercueil { 1003b5c23aa4SPaul Cercueil const unsigned int *pins; 1004b5c23aa4SPaul Cercueil unsigned int i, npins, old = 0; 1005b5c23aa4SPaul Cercueil int ret; 1006b5c23aa4SPaul Cercueil 1007b5c23aa4SPaul Cercueil ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins); 1008b5c23aa4SPaul Cercueil if (ret) 1009b5c23aa4SPaul Cercueil return ret; 1010b5c23aa4SPaul Cercueil 1011b5c23aa4SPaul Cercueil for (i = 0; i < npins; i++) { 1012b5c23aa4SPaul Cercueil if (ingenic_pinconf_get(pctldev, pins[i], config)) 1013b5c23aa4SPaul Cercueil return -ENOTSUPP; 1014b5c23aa4SPaul Cercueil 1015b5c23aa4SPaul Cercueil /* configs do not match between two pins */ 1016b5c23aa4SPaul Cercueil if (i && (old != *config)) 1017b5c23aa4SPaul Cercueil return -ENOTSUPP; 1018b5c23aa4SPaul Cercueil 1019b5c23aa4SPaul Cercueil old = *config; 1020b5c23aa4SPaul Cercueil } 1021b5c23aa4SPaul Cercueil 1022b5c23aa4SPaul Cercueil return 0; 1023b5c23aa4SPaul Cercueil } 1024b5c23aa4SPaul Cercueil 1025b5c23aa4SPaul Cercueil static int ingenic_pinconf_group_set(struct pinctrl_dev *pctldev, 1026b5c23aa4SPaul Cercueil unsigned int group, unsigned long *configs, 1027b5c23aa4SPaul Cercueil unsigned int num_configs) 1028b5c23aa4SPaul Cercueil { 1029b5c23aa4SPaul Cercueil const unsigned int *pins; 1030b5c23aa4SPaul Cercueil unsigned int i, npins; 1031b5c23aa4SPaul Cercueil int ret; 1032b5c23aa4SPaul Cercueil 1033b5c23aa4SPaul Cercueil ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins); 1034b5c23aa4SPaul Cercueil if (ret) 1035b5c23aa4SPaul Cercueil return ret; 1036b5c23aa4SPaul Cercueil 1037b5c23aa4SPaul Cercueil for (i = 0; i < npins; i++) { 1038b5c23aa4SPaul Cercueil ret = ingenic_pinconf_set(pctldev, 1039b5c23aa4SPaul Cercueil pins[i], configs, num_configs); 1040b5c23aa4SPaul Cercueil if (ret) 1041b5c23aa4SPaul Cercueil return ret; 1042b5c23aa4SPaul Cercueil } 1043b5c23aa4SPaul Cercueil 1044b5c23aa4SPaul Cercueil return 0; 1045b5c23aa4SPaul Cercueil } 1046b5c23aa4SPaul Cercueil 10475bf7b849SJulia Lawall static const struct pinconf_ops ingenic_confops = { 1048b5c23aa4SPaul Cercueil .is_generic = true, 1049b5c23aa4SPaul Cercueil .pin_config_get = ingenic_pinconf_get, 1050b5c23aa4SPaul Cercueil .pin_config_set = ingenic_pinconf_set, 1051b5c23aa4SPaul Cercueil .pin_config_group_get = ingenic_pinconf_group_get, 1052b5c23aa4SPaul Cercueil .pin_config_group_set = ingenic_pinconf_group_set, 1053b5c23aa4SPaul Cercueil }; 1054b5c23aa4SPaul Cercueil 1055b5c23aa4SPaul Cercueil static const struct regmap_config ingenic_pinctrl_regmap_config = { 1056b5c23aa4SPaul Cercueil .reg_bits = 32, 1057b5c23aa4SPaul Cercueil .val_bits = 32, 1058b5c23aa4SPaul Cercueil .reg_stride = 4, 1059b5c23aa4SPaul Cercueil }; 1060b5c23aa4SPaul Cercueil 1061b5c23aa4SPaul Cercueil static const struct of_device_id ingenic_pinctrl_of_match[] = { 1062b5c23aa4SPaul Cercueil { .compatible = "ingenic,jz4740-pinctrl", .data = (void *) ID_JZ4740 }, 1063*f2a96765SPaul Cercueil { .compatible = "ingenic,jz4725b-pinctrl", .data = (void *)ID_JZ4725B }, 1064b5c23aa4SPaul Cercueil { .compatible = "ingenic,jz4770-pinctrl", .data = (void *) ID_JZ4770 }, 1065b5c23aa4SPaul Cercueil { .compatible = "ingenic,jz4780-pinctrl", .data = (void *) ID_JZ4780 }, 1066b5c23aa4SPaul Cercueil {}, 1067b5c23aa4SPaul Cercueil }; 1068b5c23aa4SPaul Cercueil 1069e72394e2SPaul Cercueil static const struct of_device_id ingenic_gpio_of_match[] __initconst = { 1070e72394e2SPaul Cercueil { .compatible = "ingenic,jz4740-gpio", }, 1071e72394e2SPaul Cercueil { .compatible = "ingenic,jz4770-gpio", }, 1072e72394e2SPaul Cercueil { .compatible = "ingenic,jz4780-gpio", }, 1073e72394e2SPaul Cercueil {}, 1074e72394e2SPaul Cercueil }; 1075e72394e2SPaul Cercueil 1076e72394e2SPaul Cercueil static int __init ingenic_gpio_probe(struct ingenic_pinctrl *jzpc, 1077e72394e2SPaul Cercueil struct device_node *node) 1078e72394e2SPaul Cercueil { 1079e72394e2SPaul Cercueil struct ingenic_gpio_chip *jzgc; 1080e72394e2SPaul Cercueil struct device *dev = jzpc->dev; 1081e72394e2SPaul Cercueil unsigned int bank; 1082e72394e2SPaul Cercueil int err; 1083e72394e2SPaul Cercueil 1084e72394e2SPaul Cercueil err = of_property_read_u32(node, "reg", &bank); 1085e72394e2SPaul Cercueil if (err) { 1086e72394e2SPaul Cercueil dev_err(dev, "Cannot read \"reg\" property: %i\n", err); 1087e72394e2SPaul Cercueil return err; 1088e72394e2SPaul Cercueil } 1089e72394e2SPaul Cercueil 1090e72394e2SPaul Cercueil jzgc = devm_kzalloc(dev, sizeof(*jzgc), GFP_KERNEL); 1091e72394e2SPaul Cercueil if (!jzgc) 1092e72394e2SPaul Cercueil return -ENOMEM; 1093e72394e2SPaul Cercueil 1094e72394e2SPaul Cercueil jzgc->jzpc = jzpc; 1095e72394e2SPaul Cercueil jzgc->reg_base = bank * 0x100; 1096e72394e2SPaul Cercueil 1097e72394e2SPaul Cercueil jzgc->gc.label = devm_kasprintf(dev, GFP_KERNEL, "GPIO%c", 'A' + bank); 1098e72394e2SPaul Cercueil if (!jzgc->gc.label) 1099e72394e2SPaul Cercueil return -ENOMEM; 1100e72394e2SPaul Cercueil 1101e72394e2SPaul Cercueil /* DO NOT EXPAND THIS: FOR BACKWARD GPIO NUMBERSPACE COMPATIBIBILITY 1102e72394e2SPaul Cercueil * ONLY: WORK TO TRANSITION CONSUMERS TO USE THE GPIO DESCRIPTOR API IN 1103e72394e2SPaul Cercueil * <linux/gpio/consumer.h> INSTEAD. 1104e72394e2SPaul Cercueil */ 1105e72394e2SPaul Cercueil jzgc->gc.base = bank * 32; 1106e72394e2SPaul Cercueil 1107e72394e2SPaul Cercueil jzgc->gc.ngpio = 32; 1108e72394e2SPaul Cercueil jzgc->gc.parent = dev; 1109e72394e2SPaul Cercueil jzgc->gc.of_node = node; 1110e72394e2SPaul Cercueil jzgc->gc.owner = THIS_MODULE; 1111e72394e2SPaul Cercueil 1112e72394e2SPaul Cercueil jzgc->gc.set = ingenic_gpio_set; 1113e72394e2SPaul Cercueil jzgc->gc.get = ingenic_gpio_get; 1114e72394e2SPaul Cercueil jzgc->gc.direction_input = ingenic_gpio_direction_input; 1115e72394e2SPaul Cercueil jzgc->gc.direction_output = ingenic_gpio_direction_output; 1116ebd66514SPaul Cercueil jzgc->gc.get_direction = ingenic_gpio_get_direction; 1117e72394e2SPaul Cercueil 1118e72394e2SPaul Cercueil if (of_property_read_bool(node, "gpio-ranges")) { 1119e72394e2SPaul Cercueil jzgc->gc.request = gpiochip_generic_request; 1120e72394e2SPaul Cercueil jzgc->gc.free = gpiochip_generic_free; 1121e72394e2SPaul Cercueil } 1122e72394e2SPaul Cercueil 1123e72394e2SPaul Cercueil err = devm_gpiochip_add_data(dev, &jzgc->gc, jzgc); 1124e72394e2SPaul Cercueil if (err) 1125e72394e2SPaul Cercueil return err; 1126e72394e2SPaul Cercueil 1127e72394e2SPaul Cercueil jzgc->irq = irq_of_parse_and_map(node, 0); 1128e72394e2SPaul Cercueil if (!jzgc->irq) 1129e72394e2SPaul Cercueil return -EINVAL; 1130e72394e2SPaul Cercueil 1131e72394e2SPaul Cercueil jzgc->irq_chip.name = jzgc->gc.label; 1132e72394e2SPaul Cercueil jzgc->irq_chip.irq_enable = ingenic_gpio_irq_enable; 1133e72394e2SPaul Cercueil jzgc->irq_chip.irq_disable = ingenic_gpio_irq_disable; 1134e72394e2SPaul Cercueil jzgc->irq_chip.irq_unmask = ingenic_gpio_irq_unmask; 1135e72394e2SPaul Cercueil jzgc->irq_chip.irq_mask = ingenic_gpio_irq_mask; 1136e72394e2SPaul Cercueil jzgc->irq_chip.irq_ack = ingenic_gpio_irq_ack; 1137e72394e2SPaul Cercueil jzgc->irq_chip.irq_set_type = ingenic_gpio_irq_set_type; 1138e72394e2SPaul Cercueil jzgc->irq_chip.irq_set_wake = ingenic_gpio_irq_set_wake; 1139e72394e2SPaul Cercueil jzgc->irq_chip.flags = IRQCHIP_MASK_ON_SUSPEND; 1140e72394e2SPaul Cercueil 1141e72394e2SPaul Cercueil err = gpiochip_irqchip_add(&jzgc->gc, &jzgc->irq_chip, 0, 1142e72394e2SPaul Cercueil handle_level_irq, IRQ_TYPE_NONE); 1143e72394e2SPaul Cercueil if (err) 1144e72394e2SPaul Cercueil return err; 1145e72394e2SPaul Cercueil 1146e72394e2SPaul Cercueil gpiochip_set_chained_irqchip(&jzgc->gc, &jzgc->irq_chip, 1147e72394e2SPaul Cercueil jzgc->irq, ingenic_gpio_irq_handler); 1148e72394e2SPaul Cercueil return 0; 1149e72394e2SPaul Cercueil } 1150e72394e2SPaul Cercueil 11514717b11fSPaul Cercueil static int __init ingenic_pinctrl_probe(struct platform_device *pdev) 1152b5c23aa4SPaul Cercueil { 1153b5c23aa4SPaul Cercueil struct device *dev = &pdev->dev; 1154b5c23aa4SPaul Cercueil struct ingenic_pinctrl *jzpc; 1155b5c23aa4SPaul Cercueil struct pinctrl_desc *pctl_desc; 1156b5c23aa4SPaul Cercueil void __iomem *base; 1157b5c23aa4SPaul Cercueil const struct platform_device_id *id = platform_get_device_id(pdev); 1158b5c23aa4SPaul Cercueil const struct of_device_id *of_id = of_match_device( 1159b5c23aa4SPaul Cercueil ingenic_pinctrl_of_match, dev); 1160b5c23aa4SPaul Cercueil const struct ingenic_chip_info *chip_info; 1161e72394e2SPaul Cercueil struct device_node *node; 1162b5c23aa4SPaul Cercueil unsigned int i; 1163b5c23aa4SPaul Cercueil int err; 1164b5c23aa4SPaul Cercueil 1165b5c23aa4SPaul Cercueil jzpc = devm_kzalloc(dev, sizeof(*jzpc), GFP_KERNEL); 1166b5c23aa4SPaul Cercueil if (!jzpc) 1167b5c23aa4SPaul Cercueil return -ENOMEM; 1168b5c23aa4SPaul Cercueil 1169b5c23aa4SPaul Cercueil base = devm_ioremap_resource(dev, 1170b5c23aa4SPaul Cercueil platform_get_resource(pdev, IORESOURCE_MEM, 0)); 1171119fcf47SWei Yongjun if (IS_ERR(base)) 1172b5c23aa4SPaul Cercueil return PTR_ERR(base); 1173b5c23aa4SPaul Cercueil 1174b5c23aa4SPaul Cercueil jzpc->map = devm_regmap_init_mmio(dev, base, 1175b5c23aa4SPaul Cercueil &ingenic_pinctrl_regmap_config); 1176b5c23aa4SPaul Cercueil if (IS_ERR(jzpc->map)) { 1177b5c23aa4SPaul Cercueil dev_err(dev, "Failed to create regmap\n"); 1178b5c23aa4SPaul Cercueil return PTR_ERR(jzpc->map); 1179b5c23aa4SPaul Cercueil } 1180b5c23aa4SPaul Cercueil 1181b5c23aa4SPaul Cercueil jzpc->dev = dev; 1182b5c23aa4SPaul Cercueil 1183b5c23aa4SPaul Cercueil if (of_id) 1184b5c23aa4SPaul Cercueil jzpc->version = (enum jz_version)of_id->data; 1185b5c23aa4SPaul Cercueil else 1186b5c23aa4SPaul Cercueil jzpc->version = (enum jz_version)id->driver_data; 1187b5c23aa4SPaul Cercueil 1188b5c23aa4SPaul Cercueil if (jzpc->version >= ID_JZ4770) 1189b5c23aa4SPaul Cercueil chip_info = &jz4770_chip_info; 1190*f2a96765SPaul Cercueil else if (jzpc->version >= ID_JZ4725B) 1191*f2a96765SPaul Cercueil chip_info = &jz4725b_chip_info; 1192b5c23aa4SPaul Cercueil else 1193b5c23aa4SPaul Cercueil chip_info = &jz4740_chip_info; 1194b5c23aa4SPaul Cercueil jzpc->info = chip_info; 1195b5c23aa4SPaul Cercueil 1196b5c23aa4SPaul Cercueil pctl_desc = devm_kzalloc(&pdev->dev, sizeof(*pctl_desc), GFP_KERNEL); 1197b5c23aa4SPaul Cercueil if (!pctl_desc) 1198b5c23aa4SPaul Cercueil return -ENOMEM; 1199b5c23aa4SPaul Cercueil 1200b5c23aa4SPaul Cercueil /* fill in pinctrl_desc structure */ 1201b5c23aa4SPaul Cercueil pctl_desc->name = dev_name(dev); 1202b5c23aa4SPaul Cercueil pctl_desc->owner = THIS_MODULE; 1203b5c23aa4SPaul Cercueil pctl_desc->pctlops = &ingenic_pctlops; 1204b5c23aa4SPaul Cercueil pctl_desc->pmxops = &ingenic_pmxops; 1205b5c23aa4SPaul Cercueil pctl_desc->confops = &ingenic_confops; 1206b5c23aa4SPaul Cercueil pctl_desc->npins = chip_info->num_chips * PINS_PER_GPIO_CHIP; 1207a86854d0SKees Cook pctl_desc->pins = jzpc->pdesc = devm_kcalloc(&pdev->dev, 1208a86854d0SKees Cook pctl_desc->npins, sizeof(*jzpc->pdesc), GFP_KERNEL); 1209b5c23aa4SPaul Cercueil if (!jzpc->pdesc) 1210b5c23aa4SPaul Cercueil return -ENOMEM; 1211b5c23aa4SPaul Cercueil 1212b5c23aa4SPaul Cercueil for (i = 0; i < pctl_desc->npins; i++) { 1213b5c23aa4SPaul Cercueil jzpc->pdesc[i].number = i; 1214b5c23aa4SPaul Cercueil jzpc->pdesc[i].name = kasprintf(GFP_KERNEL, "P%c%d", 1215b5c23aa4SPaul Cercueil 'A' + (i / PINS_PER_GPIO_CHIP), 1216b5c23aa4SPaul Cercueil i % PINS_PER_GPIO_CHIP); 1217b5c23aa4SPaul Cercueil } 1218b5c23aa4SPaul Cercueil 1219b5c23aa4SPaul Cercueil jzpc->pctl = devm_pinctrl_register(dev, pctl_desc, jzpc); 1220e7f4c4bfSDan Carpenter if (IS_ERR(jzpc->pctl)) { 1221b5c23aa4SPaul Cercueil dev_err(dev, "Failed to register pinctrl\n"); 1222e7f4c4bfSDan Carpenter return PTR_ERR(jzpc->pctl); 1223b5c23aa4SPaul Cercueil } 1224b5c23aa4SPaul Cercueil 1225b5c23aa4SPaul Cercueil for (i = 0; i < chip_info->num_groups; i++) { 1226b5c23aa4SPaul Cercueil const struct group_desc *group = &chip_info->groups[i]; 1227b5c23aa4SPaul Cercueil 1228b5c23aa4SPaul Cercueil err = pinctrl_generic_add_group(jzpc->pctl, group->name, 1229b5c23aa4SPaul Cercueil group->pins, group->num_pins, group->data); 1230b5c23aa4SPaul Cercueil if (err) { 1231b5c23aa4SPaul Cercueil dev_err(dev, "Failed to register group %s\n", 1232b5c23aa4SPaul Cercueil group->name); 1233b5c23aa4SPaul Cercueil return err; 1234b5c23aa4SPaul Cercueil } 1235b5c23aa4SPaul Cercueil } 1236b5c23aa4SPaul Cercueil 1237b5c23aa4SPaul Cercueil for (i = 0; i < chip_info->num_functions; i++) { 1238b5c23aa4SPaul Cercueil const struct function_desc *func = &chip_info->functions[i]; 1239b5c23aa4SPaul Cercueil 1240b5c23aa4SPaul Cercueil err = pinmux_generic_add_function(jzpc->pctl, func->name, 1241b5c23aa4SPaul Cercueil func->group_names, func->num_group_names, 1242b5c23aa4SPaul Cercueil func->data); 1243b5c23aa4SPaul Cercueil if (err) { 1244b5c23aa4SPaul Cercueil dev_err(dev, "Failed to register function %s\n", 1245b5c23aa4SPaul Cercueil func->name); 1246b5c23aa4SPaul Cercueil return err; 1247b5c23aa4SPaul Cercueil } 1248b5c23aa4SPaul Cercueil } 1249b5c23aa4SPaul Cercueil 1250b5c23aa4SPaul Cercueil dev_set_drvdata(dev, jzpc->map); 1251b5c23aa4SPaul Cercueil 1252e72394e2SPaul Cercueil for_each_child_of_node(dev->of_node, node) { 1253e72394e2SPaul Cercueil if (of_match_node(ingenic_gpio_of_match, node)) { 1254e72394e2SPaul Cercueil err = ingenic_gpio_probe(jzpc, node); 1255e72394e2SPaul Cercueil if (err) 1256b5c23aa4SPaul Cercueil return err; 1257b5c23aa4SPaul Cercueil } 1258b5c23aa4SPaul Cercueil } 1259b5c23aa4SPaul Cercueil 1260b5c23aa4SPaul Cercueil return 0; 1261b5c23aa4SPaul Cercueil } 1262b5c23aa4SPaul Cercueil 1263b5c23aa4SPaul Cercueil static const struct platform_device_id ingenic_pinctrl_ids[] = { 1264b5c23aa4SPaul Cercueil { "jz4740-pinctrl", ID_JZ4740 }, 1265*f2a96765SPaul Cercueil { "jz4725b-pinctrl", ID_JZ4725B }, 1266b5c23aa4SPaul Cercueil { "jz4770-pinctrl", ID_JZ4770 }, 1267b5c23aa4SPaul Cercueil { "jz4780-pinctrl", ID_JZ4780 }, 1268b5c23aa4SPaul Cercueil {}, 1269b5c23aa4SPaul Cercueil }; 1270b5c23aa4SPaul Cercueil 1271b5c23aa4SPaul Cercueil static struct platform_driver ingenic_pinctrl_driver = { 1272b5c23aa4SPaul Cercueil .driver = { 1273b5c23aa4SPaul Cercueil .name = "pinctrl-ingenic", 1274b5c23aa4SPaul Cercueil .of_match_table = of_match_ptr(ingenic_pinctrl_of_match), 1275b5c23aa4SPaul Cercueil }, 1276b5c23aa4SPaul Cercueil .id_table = ingenic_pinctrl_ids, 1277b5c23aa4SPaul Cercueil }; 1278b5c23aa4SPaul Cercueil 1279b5c23aa4SPaul Cercueil static int __init ingenic_pinctrl_drv_register(void) 1280b5c23aa4SPaul Cercueil { 12814717b11fSPaul Cercueil return platform_driver_probe(&ingenic_pinctrl_driver, 12824717b11fSPaul Cercueil ingenic_pinctrl_probe); 1283b5c23aa4SPaul Cercueil } 1284556a36a7SPaul Cercueil subsys_initcall(ingenic_pinctrl_drv_register); 1285