0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/of.h>
0009 #include <linux/kernel.h>
0010 #include <linux/slab.h>
0011 #include <linux/of_gpio.h>
0012 #include <linux/io.h>
0013 #include <linux/of_platform.h>
0014 #include <linux/module.h>
0015
0016 #include <asm/mpc52xx.h>
0017 #include <sysdev/fsl_soc.h>
0018
0019 static DEFINE_SPINLOCK(gpio_lock);
0020
0021 struct mpc52xx_gpiochip {
0022 struct of_mm_gpio_chip mmchip;
0023 unsigned int shadow_dvo;
0024 unsigned int shadow_gpioe;
0025 unsigned int shadow_ddr;
0026 };
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 static int mpc52xx_wkup_gpio_get(struct gpio_chip *gc, unsigned int gpio)
0045 {
0046 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
0047 struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs;
0048 unsigned int ret;
0049
0050 ret = (in_8(®s->wkup_ival) >> (7 - gpio)) & 1;
0051
0052 pr_debug("%s: gpio: %d ret: %d\n", __func__, gpio, ret);
0053
0054 return ret;
0055 }
0056
0057 static inline void
0058 __mpc52xx_wkup_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
0059 {
0060 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
0061 struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc);
0062 struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs;
0063
0064 if (val)
0065 chip->shadow_dvo |= 1 << (7 - gpio);
0066 else
0067 chip->shadow_dvo &= ~(1 << (7 - gpio));
0068
0069 out_8(®s->wkup_dvo, chip->shadow_dvo);
0070 }
0071
0072 static void
0073 mpc52xx_wkup_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
0074 {
0075 unsigned long flags;
0076
0077 spin_lock_irqsave(&gpio_lock, flags);
0078
0079 __mpc52xx_wkup_gpio_set(gc, gpio, val);
0080
0081 spin_unlock_irqrestore(&gpio_lock, flags);
0082
0083 pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
0084 }
0085
0086 static int mpc52xx_wkup_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
0087 {
0088 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
0089 struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc);
0090 struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs;
0091 unsigned long flags;
0092
0093 spin_lock_irqsave(&gpio_lock, flags);
0094
0095
0096 chip->shadow_ddr &= ~(1 << (7 - gpio));
0097 out_8(®s->wkup_ddr, chip->shadow_ddr);
0098
0099
0100 chip->shadow_gpioe |= 1 << (7 - gpio);
0101 out_8(®s->wkup_gpioe, chip->shadow_gpioe);
0102
0103 spin_unlock_irqrestore(&gpio_lock, flags);
0104
0105 return 0;
0106 }
0107
0108 static int
0109 mpc52xx_wkup_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
0110 {
0111 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
0112 struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs;
0113 struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc);
0114 unsigned long flags;
0115
0116 spin_lock_irqsave(&gpio_lock, flags);
0117
0118 __mpc52xx_wkup_gpio_set(gc, gpio, val);
0119
0120
0121 chip->shadow_ddr |= 1 << (7 - gpio);
0122 out_8(®s->wkup_ddr, chip->shadow_ddr);
0123
0124
0125 chip->shadow_gpioe |= 1 << (7 - gpio);
0126 out_8(®s->wkup_gpioe, chip->shadow_gpioe);
0127
0128 spin_unlock_irqrestore(&gpio_lock, flags);
0129
0130 pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
0131
0132 return 0;
0133 }
0134
0135 static int mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev)
0136 {
0137 struct mpc52xx_gpiochip *chip;
0138 struct mpc52xx_gpio_wkup __iomem *regs;
0139 struct gpio_chip *gc;
0140 int ret;
0141
0142 chip = devm_kzalloc(&ofdev->dev, sizeof(*chip), GFP_KERNEL);
0143 if (!chip)
0144 return -ENOMEM;
0145
0146 platform_set_drvdata(ofdev, chip);
0147
0148 gc = &chip->mmchip.gc;
0149
0150 gc->ngpio = 8;
0151 gc->direction_input = mpc52xx_wkup_gpio_dir_in;
0152 gc->direction_output = mpc52xx_wkup_gpio_dir_out;
0153 gc->get = mpc52xx_wkup_gpio_get;
0154 gc->set = mpc52xx_wkup_gpio_set;
0155
0156 ret = of_mm_gpiochip_add_data(ofdev->dev.of_node, &chip->mmchip, chip);
0157 if (ret)
0158 return ret;
0159
0160 regs = chip->mmchip.regs;
0161 chip->shadow_gpioe = in_8(®s->wkup_gpioe);
0162 chip->shadow_ddr = in_8(®s->wkup_ddr);
0163 chip->shadow_dvo = in_8(®s->wkup_dvo);
0164
0165 return 0;
0166 }
0167
0168 static int mpc52xx_gpiochip_remove(struct platform_device *ofdev)
0169 {
0170 struct mpc52xx_gpiochip *chip = platform_get_drvdata(ofdev);
0171
0172 of_mm_gpiochip_remove(&chip->mmchip);
0173
0174 return 0;
0175 }
0176
0177 static const struct of_device_id mpc52xx_wkup_gpiochip_match[] = {
0178 { .compatible = "fsl,mpc5200-gpio-wkup", },
0179 {}
0180 };
0181
0182 static struct platform_driver mpc52xx_wkup_gpiochip_driver = {
0183 .driver = {
0184 .name = "mpc5200-gpio-wkup",
0185 .of_match_table = mpc52xx_wkup_gpiochip_match,
0186 },
0187 .probe = mpc52xx_wkup_gpiochip_probe,
0188 .remove = mpc52xx_gpiochip_remove,
0189 };
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208 static int mpc52xx_simple_gpio_get(struct gpio_chip *gc, unsigned int gpio)
0209 {
0210 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
0211 struct mpc52xx_gpio __iomem *regs = mm_gc->regs;
0212 unsigned int ret;
0213
0214 ret = (in_be32(®s->simple_ival) >> (31 - gpio)) & 1;
0215
0216 return ret;
0217 }
0218
0219 static inline void
0220 __mpc52xx_simple_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
0221 {
0222 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
0223 struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc);
0224 struct mpc52xx_gpio __iomem *regs = mm_gc->regs;
0225
0226 if (val)
0227 chip->shadow_dvo |= 1 << (31 - gpio);
0228 else
0229 chip->shadow_dvo &= ~(1 << (31 - gpio));
0230 out_be32(®s->simple_dvo, chip->shadow_dvo);
0231 }
0232
0233 static void
0234 mpc52xx_simple_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
0235 {
0236 unsigned long flags;
0237
0238 spin_lock_irqsave(&gpio_lock, flags);
0239
0240 __mpc52xx_simple_gpio_set(gc, gpio, val);
0241
0242 spin_unlock_irqrestore(&gpio_lock, flags);
0243
0244 pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
0245 }
0246
0247 static int mpc52xx_simple_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
0248 {
0249 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
0250 struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc);
0251 struct mpc52xx_gpio __iomem *regs = mm_gc->regs;
0252 unsigned long flags;
0253
0254 spin_lock_irqsave(&gpio_lock, flags);
0255
0256
0257 chip->shadow_ddr &= ~(1 << (31 - gpio));
0258 out_be32(®s->simple_ddr, chip->shadow_ddr);
0259
0260
0261 chip->shadow_gpioe |= 1 << (31 - gpio);
0262 out_be32(®s->simple_gpioe, chip->shadow_gpioe);
0263
0264 spin_unlock_irqrestore(&gpio_lock, flags);
0265
0266 return 0;
0267 }
0268
0269 static int
0270 mpc52xx_simple_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
0271 {
0272 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
0273 struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc);
0274 struct mpc52xx_gpio __iomem *regs = mm_gc->regs;
0275 unsigned long flags;
0276
0277 spin_lock_irqsave(&gpio_lock, flags);
0278
0279
0280 __mpc52xx_simple_gpio_set(gc, gpio, val);
0281
0282
0283 chip->shadow_ddr |= 1 << (31 - gpio);
0284 out_be32(®s->simple_ddr, chip->shadow_ddr);
0285
0286
0287 chip->shadow_gpioe |= 1 << (31 - gpio);
0288 out_be32(®s->simple_gpioe, chip->shadow_gpioe);
0289
0290 spin_unlock_irqrestore(&gpio_lock, flags);
0291
0292 pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
0293
0294 return 0;
0295 }
0296
0297 static int mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev)
0298 {
0299 struct mpc52xx_gpiochip *chip;
0300 struct gpio_chip *gc;
0301 struct mpc52xx_gpio __iomem *regs;
0302 int ret;
0303
0304 chip = devm_kzalloc(&ofdev->dev, sizeof(*chip), GFP_KERNEL);
0305 if (!chip)
0306 return -ENOMEM;
0307
0308 platform_set_drvdata(ofdev, chip);
0309
0310 gc = &chip->mmchip.gc;
0311
0312 gc->ngpio = 32;
0313 gc->direction_input = mpc52xx_simple_gpio_dir_in;
0314 gc->direction_output = mpc52xx_simple_gpio_dir_out;
0315 gc->get = mpc52xx_simple_gpio_get;
0316 gc->set = mpc52xx_simple_gpio_set;
0317
0318 ret = of_mm_gpiochip_add_data(ofdev->dev.of_node, &chip->mmchip, chip);
0319 if (ret)
0320 return ret;
0321
0322 regs = chip->mmchip.regs;
0323 chip->shadow_gpioe = in_be32(®s->simple_gpioe);
0324 chip->shadow_ddr = in_be32(®s->simple_ddr);
0325 chip->shadow_dvo = in_be32(®s->simple_dvo);
0326
0327 return 0;
0328 }
0329
0330 static const struct of_device_id mpc52xx_simple_gpiochip_match[] = {
0331 { .compatible = "fsl,mpc5200-gpio", },
0332 {}
0333 };
0334
0335 static struct platform_driver mpc52xx_simple_gpiochip_driver = {
0336 .driver = {
0337 .name = "mpc5200-gpio",
0338 .of_match_table = mpc52xx_simple_gpiochip_match,
0339 },
0340 .probe = mpc52xx_simple_gpiochip_probe,
0341 .remove = mpc52xx_gpiochip_remove,
0342 };
0343
0344 static struct platform_driver * const drivers[] = {
0345 &mpc52xx_wkup_gpiochip_driver,
0346 &mpc52xx_simple_gpiochip_driver,
0347 };
0348
0349 static int __init mpc52xx_gpio_init(void)
0350 {
0351 return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
0352 }
0353
0354
0355 subsys_initcall(mpc52xx_gpio_init);
0356
0357 static void __exit mpc52xx_gpio_exit(void)
0358 {
0359 platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
0360 }
0361 module_exit(mpc52xx_gpio_exit);
0362
0363 MODULE_DESCRIPTION("Freescale MPC52xx gpio driver");
0364 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de");
0365 MODULE_LICENSE("GPL v2");
0366