| 1 | From 13e754b5fff5be1930e2b8fe534a52b608c9e479 Mon Sep 17 00:00:00 2001 |
| 2 | From: John Crispin <blogic@openwrt.org> |
| 3 | Date: Mon, 3 Dec 2012 19:27:28 +0100 |
| 4 | Subject: [PATCH] PINCTRL: lantiq: fixes |
| 5 | |
| 6 | --- |
| 7 | drivers/pinctrl/pinctrl-lantiq.c | 54 ++++++++++++++++++----------- |
| 8 | drivers/pinctrl/pinctrl-lantiq.h | 1 + |
| 9 | drivers/pinctrl/pinctrl-xway.c | 70 ++++++++++++++++++++++++++++++++++---- |
| 10 | 3 files changed, 99 insertions(+), 26 deletions(-) |
| 11 | |
| 12 | Index: linux-3.7-rc8/drivers/pinctrl/pinctrl-lantiq.c |
| 13 | =================================================================== |
| 14 | --- linux-3.7-rc8.orig/drivers/pinctrl/pinctrl-lantiq.c 2012-12-03 20:22:37.000000000 +0100 |
| 15 | +++ linux-3.7-rc8/drivers/pinctrl/pinctrl-lantiq.c 2012-12-14 22:59:40.687563565 +0100 |
| 16 | @@ -64,11 +64,13 @@ |
| 17 | seq_printf(s, " %s", dev_name(pctldev->dev)); |
| 18 | } |
| 19 | |
| 20 | -static int ltq_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev, |
| 21 | +static void ltq_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev, |
| 22 | struct device_node *np, |
| 23 | struct pinctrl_map **map) |
| 24 | { |
| 25 | struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctldev); |
| 26 | + struct property *pins = of_find_property(np, "lantiq,pins", NULL); |
| 27 | + struct property *groups = of_find_property(np, "lantiq,groups", NULL); |
| 28 | unsigned long configs[3]; |
| 29 | unsigned num_configs = 0; |
| 30 | struct property *prop; |
| 31 | @@ -76,8 +78,20 @@ |
| 32 | const char *function; |
| 33 | int ret, i; |
| 34 | |
| 35 | + if (!pins && !groups) { |
| 36 | + dev_err(pctldev->dev, "%s defines neither pins nor groups\n", |
| 37 | + np->name); |
| 38 | + return; |
| 39 | + } |
| 40 | + |
| 41 | + if (pins && groups) { |
| 42 | + dev_err(pctldev->dev, "%s defines both pins and groups\n", |
| 43 | + np->name); |
| 44 | + return; |
| 45 | + } |
| 46 | + |
| 47 | ret = of_property_read_string(np, "lantiq,function", &function); |
| 48 | - if (!ret) { |
| 49 | + if (groups && !ret) { |
| 50 | of_property_for_each_string(np, "lantiq,groups", prop, group) { |
| 51 | (*map)->type = PIN_MAP_TYPE_MUX_GROUP; |
| 52 | (*map)->name = function; |
| 53 | @@ -85,11 +99,6 @@ |
| 54 | (*map)->data.mux.function = function; |
| 55 | (*map)++; |
| 56 | } |
| 57 | - if (of_find_property(np, "lantiq,pins", NULL)) |
| 58 | - dev_err(pctldev->dev, |
| 59 | - "%s mixes pins and groups settings\n", |
| 60 | - np->name); |
| 61 | - return 0; |
| 62 | } |
| 63 | |
| 64 | for (i = 0; i < info->num_params; i++) { |
| 65 | @@ -103,7 +112,7 @@ |
| 66 | } |
| 67 | |
| 68 | if (!num_configs) |
| 69 | - return -EINVAL; |
| 70 | + return; |
| 71 | |
| 72 | of_property_for_each_string(np, "lantiq,pins", prop, pin) { |
| 73 | (*map)->data.configs.configs = kmemdup(configs, |
| 74 | @@ -115,7 +124,16 @@ |
| 75 | (*map)->data.configs.num_configs = num_configs; |
| 76 | (*map)++; |
| 77 | } |
| 78 | - return 0; |
| 79 | + of_property_for_each_string(np, "lantiq,groups", prop, group) { |
| 80 | + (*map)->data.configs.configs = kmemdup(configs, |
| 81 | + num_configs * sizeof(unsigned long), |
| 82 | + GFP_KERNEL); |
| 83 | + (*map)->type = PIN_MAP_TYPE_CONFIGS_GROUP; |
| 84 | + (*map)->name = group; |
| 85 | + (*map)->data.configs.group_or_pin = group; |
| 86 | + (*map)->data.configs.num_configs = num_configs; |
| 87 | + (*map)++; |
| 88 | + } |
| 89 | } |
| 90 | |
| 91 | static int ltq_pinctrl_dt_subnode_size(struct device_node *np) |
| 92 | @@ -135,23 +153,19 @@ |
| 93 | { |
| 94 | struct pinctrl_map *tmp; |
| 95 | struct device_node *np; |
| 96 | - int ret; |
| 97 | + int max_maps = 0; |
| 98 | |
| 99 | - *num_maps = 0; |
| 100 | for_each_child_of_node(np_config, np) |
| 101 | - *num_maps += ltq_pinctrl_dt_subnode_size(np); |
| 102 | - *map = kzalloc(*num_maps * sizeof(struct pinctrl_map), GFP_KERNEL); |
| 103 | + max_maps += ltq_pinctrl_dt_subnode_size(np); |
| 104 | + *map = kzalloc(max_maps * sizeof(struct pinctrl_map) * 2, GFP_KERNEL); |
| 105 | if (!*map) |
| 106 | return -ENOMEM; |
| 107 | tmp = *map; |
| 108 | |
| 109 | - for_each_child_of_node(np_config, np) { |
| 110 | - ret = ltq_pinctrl_dt_subnode_to_map(pctldev, np, &tmp); |
| 111 | - if (ret < 0) { |
| 112 | - ltq_pinctrl_dt_free_map(pctldev, *map, *num_maps); |
| 113 | - return ret; |
| 114 | - } |
| 115 | - } |
| 116 | + for_each_child_of_node(np_config, np) |
| 117 | + ltq_pinctrl_dt_subnode_to_map(pctldev, np, &tmp); |
| 118 | + *num_maps = ((int)(tmp - *map)); |
| 119 | + |
| 120 | return 0; |
| 121 | } |
| 122 | |
| 123 | Index: linux-3.7-rc8/drivers/pinctrl/pinctrl-lantiq.h |
| 124 | =================================================================== |
| 125 | --- linux-3.7-rc8.orig/drivers/pinctrl/pinctrl-lantiq.h 2012-12-03 20:22:37.000000000 +0100 |
| 126 | +++ linux-3.7-rc8/drivers/pinctrl/pinctrl-lantiq.h 2012-12-14 22:55:26.591557194 +0100 |
| 127 | @@ -34,6 +34,7 @@ |
| 128 | LTQ_PINCONF_PARAM_OPEN_DRAIN, |
| 129 | LTQ_PINCONF_PARAM_DRIVE_CURRENT, |
| 130 | LTQ_PINCONF_PARAM_SLEW_RATE, |
| 131 | + LTQ_PINCONF_PARAM_OUTPUT, |
| 132 | }; |
| 133 | |
| 134 | struct ltq_cfg_param { |
| 135 | Index: linux-3.7-rc8/drivers/pinctrl/pinctrl-xway.c |
| 136 | =================================================================== |
| 137 | --- linux-3.7-rc8.orig/drivers/pinctrl/pinctrl-xway.c 2012-12-14 22:55:26.567557195 +0100 |
| 138 | +++ linux-3.7-rc8/drivers/pinctrl/pinctrl-xway.c 2012-12-14 22:55:26.595557195 +0100 |
| 139 | @@ -443,7 +443,7 @@ |
| 140 | else |
| 141 | reg = GPIO_OD(pin); |
| 142 | *config = LTQ_PINCONF_PACK(param, |
| 143 | - !!gpio_getbit(info->membase[0], reg, PORT_PIN(pin))); |
| 144 | + !gpio_getbit(info->membase[0], reg, PORT_PIN(pin))); |
| 145 | break; |
| 146 | |
| 147 | case LTQ_PINCONF_PARAM_PULL: |
| 148 | @@ -466,6 +466,11 @@ |
| 149 | *config = LTQ_PINCONF_PACK(param, 1); |
| 150 | break; |
| 151 | |
| 152 | + case LTQ_PINCONF_PARAM_OUTPUT: |
| 153 | + reg = GPIO_DIR(pin); |
| 154 | + *config = LTQ_PINCONF_PACK(param, |
| 155 | + gpio_getbit(info->membase[0], reg, PORT_PIN(pin))); |
| 156 | + break; |
| 157 | default: |
| 158 | dev_err(pctldev->dev, "Invalid config param %04x\n", param); |
| 159 | return -ENOTSUPP; |
| 160 | @@ -489,7 +494,10 @@ |
| 161 | reg = GPIO3_OD; |
| 162 | else |
| 163 | reg = GPIO_OD(pin); |
| 164 | - gpio_setbit(info->membase[0], reg, PORT_PIN(pin)); |
| 165 | + if (arg == 0) |
| 166 | + gpio_setbit(info->membase[0], reg, PORT_PIN(pin)); |
| 167 | + else |
| 168 | + gpio_clearbit(info->membase[0], reg, PORT_PIN(pin)); |
| 169 | break; |
| 170 | |
| 171 | case LTQ_PINCONF_PARAM_PULL: |
| 172 | @@ -515,6 +523,14 @@ |
| 173 | dev_err(pctldev->dev, "Invalid pull value %d\n", arg); |
| 174 | break; |
| 175 | |
| 176 | + case LTQ_PINCONF_PARAM_OUTPUT: |
| 177 | + reg = GPIO_DIR(pin); |
| 178 | + if (arg == 0) |
| 179 | + gpio_clearbit(info->membase[0], reg, PORT_PIN(pin)); |
| 180 | + else |
| 181 | + gpio_setbit(info->membase[0], reg, PORT_PIN(pin)); |
| 182 | + break; |
| 183 | + |
| 184 | default: |
| 185 | dev_err(pctldev->dev, "Invalid config param %04x\n", param); |
| 186 | return -ENOTSUPP; |
| 187 | @@ -522,9 +538,25 @@ |
| 188 | return 0; |
| 189 | } |
| 190 | |
| 191 | +int xway_pinconf_group_set(struct pinctrl_dev *pctldev, |
| 192 | + unsigned selector, |
| 193 | + unsigned long config) |
| 194 | +{ |
| 195 | + struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctldev); |
| 196 | + int i, ret = 0; |
| 197 | + |
| 198 | + for (i = 0; i < info->grps[selector].npins && !ret; i++) |
| 199 | + ret = xway_pinconf_set(pctldev, |
| 200 | + info->grps[selector].pins[i], config); |
| 201 | + |
| 202 | + return ret; |
| 203 | +} |
| 204 | + |
| 205 | + |
| 206 | struct pinconf_ops xway_pinconf_ops = { |
| 207 | .pin_config_get = xway_pinconf_get, |
| 208 | .pin_config_set = xway_pinconf_set, |
| 209 | + .pin_config_group_set = xway_pinconf_group_set, |
| 210 | }; |
| 211 | |
| 212 | static struct pinctrl_desc xway_pctrl_desc = { |
| 213 | @@ -532,10 +564,9 @@ |
| 214 | .confops = &xway_pinconf_ops, |
| 215 | }; |
| 216 | |
| 217 | -static inline int xway_mux_apply(struct pinctrl_dev *pctrldev, |
| 218 | +static int mux_apply(struct ltq_pinmux_info *info, |
| 219 | int pin, int mux) |
| 220 | { |
| 221 | - struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev); |
| 222 | int port = PORT(pin); |
| 223 | u32 alt1_reg = GPIO_ALT1(pin); |
| 224 | |
| 225 | @@ -555,9 +586,18 @@ |
| 226 | return 0; |
| 227 | } |
| 228 | |
| 229 | +static inline int xway_mux_apply(struct pinctrl_dev *pctrldev, |
| 230 | + int pin, int mux) |
| 231 | +{ |
| 232 | + struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev); |
| 233 | + |
| 234 | + return mux_apply(info, pin, mux); |
| 235 | +} |
| 236 | + |
| 237 | static const struct ltq_cfg_param xway_cfg_params[] = { |
| 238 | {"lantiq,pull", LTQ_PINCONF_PARAM_PULL}, |
| 239 | {"lantiq,open-drain", LTQ_PINCONF_PARAM_OPEN_DRAIN}, |
| 240 | + {"lantiq,output", LTQ_PINCONF_PARAM_OUTPUT}, |
| 241 | }; |
| 242 | |
| 243 | static struct ltq_pinmux_info xway_info = { |
| 244 | @@ -598,6 +638,10 @@ |
| 245 | { |
| 246 | struct ltq_pinmux_info *info = dev_get_drvdata(chip->dev); |
| 247 | |
| 248 | + if (PORT(pin) == PORT3) |
| 249 | + gpio_setbit(info->membase[0], GPIO3_OD, PORT_PIN(pin)); |
| 250 | + else |
| 251 | + gpio_setbit(info->membase[0], GPIO_OD(pin), PORT_PIN(pin)); |
| 252 | gpio_setbit(info->membase[0], GPIO_DIR(pin), PORT_PIN(pin)); |
| 253 | xway_gpio_set(chip, pin, val); |
| 254 | |
| 255 | @@ -618,6 +662,18 @@ |
| 256 | pinctrl_free_gpio(gpio); |
| 257 | } |
| 258 | |
| 259 | +static int xway_gpio_to_irq(struct gpio_chip *chip, unsigned offset) |
| 260 | +{ |
| 261 | + struct ltq_pinmux_info *info = dev_get_drvdata(chip->dev); |
| 262 | + int i; |
| 263 | + |
| 264 | + for (i = 0; i < info->num_exin; i++) |
| 265 | + if (info->exin[i] == offset) |
| 266 | + return ltq_eiu_get_irq(i); |
| 267 | + |
| 268 | + return -1; |
| 269 | +} |
| 270 | + |
| 271 | static struct gpio_chip xway_chip = { |
| 272 | .label = "gpio-xway", |
| 273 | .direction_input = xway_gpio_dir_in, |
| 274 | @@ -626,6 +682,7 @@ |
| 275 | .set = xway_gpio_set, |
| 276 | .request = xway_gpio_req, |
| 277 | .free = xway_gpio_free, |
| 278 | + .to_irq = xway_gpio_to_irq, |
| 279 | .base = -1, |
| 280 | }; |
| 281 | |
| 282 | |