1aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov/* 2c103de240439dfee24ac50eb99c8be3a30d13323Grant Likely * Generic driver for memory-mapped GPIO controllers. 3aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * 4aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * Copyright 2008 MontaVista Software, Inc. 5aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * Copyright 2008,2010 Anton Vorontsov <cbouatmailru@gmail.com> 6aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * 7aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * This program is free software; you can redistribute it and/or modify it 8aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * under the terms of the GNU General Public License as published by the 9aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * Free Software Foundation; either version 2 of the License, or (at your 10aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * option) any later version. 11aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * 12aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * ....``.```~~~~````.`.`.`.`.```````'',,,.........`````......`....... 13aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * ...`` ```````.. 14aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * ..The simplest form of a GPIO controller that the driver supports is`` 15aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * `.just a single "data" register, where GPIO state can be read and/or ` 16aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * `,..written. ,,..``~~~~ .....``.`.`.~~.```.`.........``````.``````` 17aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * ````````` 18aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov ___ 19aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov_/~~|___/~| . ```~~~~~~ ___/___\___ ,~.`.`.`.`````.~~...,,,,... 20aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov__________|~$@~~~ %~ /o*o*o*o*o*o\ .. Implementing such a GPIO . 21aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsovo ` ~~~~\___/~~~~ ` controller in FPGA is ,.` 22aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov `....trivial..'~`.```.``` 23aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * ``````` 24aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * .```````~~~~`..`.``.``. 25aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * . The driver supports `... ,..```.`~~~```````````````....````.``,, 26aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * . big-endian notation, just`. .. A bit more sophisticated controllers , 27aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * . register the device with -be`. .with a pair of set/clear-bit registers , 28aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * `.. suffix. ```~~`````....`.` . affecting the data register and the .` 29aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * ``.`.``...``` ```.. output pins are also supported.` 30aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * ^^ `````.`````````.,``~``~``~~`````` 31aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * . ^^ 32aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * ,..`.`.`...````````````......`.`.`.`.`.`..`.`.`.. 33aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * .. The expectation is that in at least some cases . ,-~~~-, 34aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * .this will be used with roll-your-own ASIC/FPGA .` \ / 35aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * .logic in Verilog or VHDL. ~~~`````````..`````~~` \ / 36aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * ..````````......``````````` \o_ 37aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * | 38aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * ^^ / \ 39aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * 40aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * ...`````~~`.....``.`..........``````.`.``.```........``. 41aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * ` 8, 16, 32 and 64 bits registers are supported, and``. 42aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * . the number of GPIOs is determined by the width of ~ 43aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * .. the registers. ,............```.`.`..`.`.~~~.`.`.`~ 44aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov * `.......````.``` 45aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov */ 46aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov 47aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov#include <linux/init.h> 48280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles#include <linux/err.h> 49aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov#include <linux/bug.h> 50aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov#include <linux/kernel.h> 51aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov#include <linux/module.h> 52aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov#include <linux/spinlock.h> 53aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov#include <linux/compiler.h> 54aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov#include <linux/types.h> 55aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov#include <linux/errno.h> 56aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov#include <linux/log2.h> 57aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov#include <linux/ioport.h> 58aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov#include <linux/io.h> 59aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov#include <linux/gpio.h> 60aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov#include <linux/slab.h> 61aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov#include <linux/platform_device.h> 62aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov#include <linux/mod_devicetable.h> 63aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov#include <linux/basic_mmio_gpio.h> 64aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov 658467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Ilesstatic void bgpio_write8(void __iomem *reg, unsigned long data) 66aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov{ 67fd9962352105f19711d55cc2caaf75b2e201598bJamie Iles writeb(data, reg); 68aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov} 69aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov 708467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Ilesstatic unsigned long bgpio_read8(void __iomem *reg) 71aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov{ 72fd9962352105f19711d55cc2caaf75b2e201598bJamie Iles return readb(reg); 738467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles} 748467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles 758467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Ilesstatic void bgpio_write16(void __iomem *reg, unsigned long data) 768467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles{ 77fd9962352105f19711d55cc2caaf75b2e201598bJamie Iles writew(data, reg); 788467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles} 798467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles 808467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Ilesstatic unsigned long bgpio_read16(void __iomem *reg) 818467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles{ 82fd9962352105f19711d55cc2caaf75b2e201598bJamie Iles return readw(reg); 838467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles} 848467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles 858467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Ilesstatic void bgpio_write32(void __iomem *reg, unsigned long data) 868467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles{ 87fd9962352105f19711d55cc2caaf75b2e201598bJamie Iles writel(data, reg); 888467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles} 898467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles 908467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Ilesstatic unsigned long bgpio_read32(void __iomem *reg) 918467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles{ 92fd9962352105f19711d55cc2caaf75b2e201598bJamie Iles return readl(reg); 938467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles} 948467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles 95aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov#if BITS_PER_LONG >= 64 968467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Ilesstatic void bgpio_write64(void __iomem *reg, unsigned long data) 978467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles{ 98fd9962352105f19711d55cc2caaf75b2e201598bJamie Iles writeq(data, reg); 998467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles} 1008467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles 1018467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Ilesstatic unsigned long bgpio_read64(void __iomem *reg) 1028467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles{ 103fd9962352105f19711d55cc2caaf75b2e201598bJamie Iles return readq(reg); 104aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov} 1058467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles#endif /* BITS_PER_LONG >= 64 */ 106aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov 107aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsovstatic unsigned long bgpio_pin2mask(struct bgpio_chip *bgc, unsigned int pin) 108aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov{ 1098467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles return 1 << pin; 1108467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles} 1118467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles 1128467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Ilesstatic unsigned long bgpio_pin2mask_be(struct bgpio_chip *bgc, 1138467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles unsigned int pin) 1148467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles{ 1158467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles return 1 << (bgc->bits - 1 - pin); 116aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov} 117aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov 118aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsovstatic int bgpio_get(struct gpio_chip *gc, unsigned int gpio) 119aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov{ 120aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov struct bgpio_chip *bgc = to_bgpio_chip(gc); 121aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov 1228467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles return bgc->read_reg(bgc->reg_dat) & bgc->pin2mask(bgc, gpio); 123aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov} 124aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov 125aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsovstatic void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) 126aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov{ 127aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov struct bgpio_chip *bgc = to_bgpio_chip(gc); 1288467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles unsigned long mask = bgc->pin2mask(bgc, gpio); 129aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov unsigned long flags; 130aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov 131aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov spin_lock_irqsave(&bgc->lock, flags); 132aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov 133aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov if (val) 134aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov bgc->data |= mask; 135aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov else 136aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov bgc->data &= ~mask; 137aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov 1388467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles bgc->write_reg(bgc->reg_dat, bgc->data); 139aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov 140aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov spin_unlock_irqrestore(&bgc->lock, flags); 141aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov} 142aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov 143e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Ilesstatic void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio, 144e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles int val) 145e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles{ 146e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles struct bgpio_chip *bgc = to_bgpio_chip(gc); 147e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles unsigned long mask = bgc->pin2mask(bgc, gpio); 148e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles 149e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles if (val) 150e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles bgc->write_reg(bgc->reg_set, mask); 151e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles else 152e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles bgc->write_reg(bgc->reg_clr, mask); 153e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles} 154e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles 155dd86a0cc5e35161538c10e35eb85e2ad0adfe14dJamie Ilesstatic void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val) 156dd86a0cc5e35161538c10e35eb85e2ad0adfe14dJamie Iles{ 157dd86a0cc5e35161538c10e35eb85e2ad0adfe14dJamie Iles struct bgpio_chip *bgc = to_bgpio_chip(gc); 158dd86a0cc5e35161538c10e35eb85e2ad0adfe14dJamie Iles unsigned long mask = bgc->pin2mask(bgc, gpio); 159dd86a0cc5e35161538c10e35eb85e2ad0adfe14dJamie Iles unsigned long flags; 160dd86a0cc5e35161538c10e35eb85e2ad0adfe14dJamie Iles 161dd86a0cc5e35161538c10e35eb85e2ad0adfe14dJamie Iles spin_lock_irqsave(&bgc->lock, flags); 162dd86a0cc5e35161538c10e35eb85e2ad0adfe14dJamie Iles 163dd86a0cc5e35161538c10e35eb85e2ad0adfe14dJamie Iles if (val) 164dd86a0cc5e35161538c10e35eb85e2ad0adfe14dJamie Iles bgc->data |= mask; 165dd86a0cc5e35161538c10e35eb85e2ad0adfe14dJamie Iles else 166dd86a0cc5e35161538c10e35eb85e2ad0adfe14dJamie Iles bgc->data &= ~mask; 167dd86a0cc5e35161538c10e35eb85e2ad0adfe14dJamie Iles 168dd86a0cc5e35161538c10e35eb85e2ad0adfe14dJamie Iles bgc->write_reg(bgc->reg_set, bgc->data); 169dd86a0cc5e35161538c10e35eb85e2ad0adfe14dJamie Iles 170dd86a0cc5e35161538c10e35eb85e2ad0adfe14dJamie Iles spin_unlock_irqrestore(&bgc->lock, flags); 171dd86a0cc5e35161538c10e35eb85e2ad0adfe14dJamie Iles} 172dd86a0cc5e35161538c10e35eb85e2ad0adfe14dJamie Iles 17331029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Ilesstatic int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio) 17431029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles{ 17531029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles return 0; 17631029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles} 17731029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles 17831029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Ilesstatic int bgpio_simple_dir_out(struct gpio_chip *gc, unsigned int gpio, 17931029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles int val) 18031029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles{ 18131029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles gc->set(gc, gpio, val); 18231029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles 18331029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles return 0; 18431029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles} 18531029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles 186aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsovstatic int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) 187aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov{ 18831029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles struct bgpio_chip *bgc = to_bgpio_chip(gc); 18931029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles unsigned long flags; 19031029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles 19131029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles spin_lock_irqsave(&bgc->lock, flags); 19231029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles 19331029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles bgc->dir &= ~bgc->pin2mask(bgc, gpio); 19431029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles bgc->write_reg(bgc->reg_dir, bgc->dir); 19531029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles 19631029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles spin_unlock_irqrestore(&bgc->lock, flags); 19731029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles 198aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov return 0; 199aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov} 200aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov 201aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsovstatic int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) 202aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov{ 20331029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles struct bgpio_chip *bgc = to_bgpio_chip(gc); 20431029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles unsigned long flags; 20531029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles 20631029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles gc->set(gc, gpio, val); 20731029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles 20831029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles spin_lock_irqsave(&bgc->lock, flags); 20931029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles 21031029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles bgc->dir |= bgc->pin2mask(bgc, gpio); 21131029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles bgc->write_reg(bgc->reg_dir, bgc->dir); 21231029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles 21331029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles spin_unlock_irqrestore(&bgc->lock, flags); 21431029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles 21531029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles return 0; 21631029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles} 21731029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles 21831029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Ilesstatic int bgpio_dir_in_inv(struct gpio_chip *gc, unsigned int gpio) 21931029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles{ 22031029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles struct bgpio_chip *bgc = to_bgpio_chip(gc); 22131029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles unsigned long flags; 22231029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles 22331029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles spin_lock_irqsave(&bgc->lock, flags); 22431029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles 22531029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles bgc->dir |= bgc->pin2mask(bgc, gpio); 22631029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles bgc->write_reg(bgc->reg_dir, bgc->dir); 22731029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles 22831029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles spin_unlock_irqrestore(&bgc->lock, flags); 22931029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles 23031029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles return 0; 23131029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles} 23231029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles 23331029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Ilesstatic int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val) 23431029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles{ 23531029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles struct bgpio_chip *bgc = to_bgpio_chip(gc); 23631029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles unsigned long flags; 23731029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles 238e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles gc->set(gc, gpio, val); 239e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles 24031029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles spin_lock_irqsave(&bgc->lock, flags); 24131029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles 24231029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles bgc->dir &= ~bgc->pin2mask(bgc, gpio); 24331029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles bgc->write_reg(bgc->reg_dir, bgc->dir); 24431029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles 24531029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles spin_unlock_irqrestore(&bgc->lock, flags); 24631029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles 247aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov return 0; 248aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov} 249aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov 250280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Ilesstatic int bgpio_setup_accessors(struct device *dev, 251280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles struct bgpio_chip *bgc, 252280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles bool be) 253aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov{ 2548467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles 2558467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles switch (bgc->bits) { 2568467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles case 8: 2578467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles bgc->read_reg = bgpio_read8; 2588467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles bgc->write_reg = bgpio_write8; 2598467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles break; 2608467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles case 16: 2618467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles bgc->read_reg = bgpio_read16; 2628467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles bgc->write_reg = bgpio_write16; 2638467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles break; 2648467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles case 32: 2658467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles bgc->read_reg = bgpio_read32; 2668467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles bgc->write_reg = bgpio_write32; 2678467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles break; 2688467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles#if BITS_PER_LONG >= 64 2698467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles case 64: 2708467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles bgc->read_reg = bgpio_read64; 2718467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles bgc->write_reg = bgpio_write64; 2728467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles break; 2738467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles#endif /* BITS_PER_LONG >= 64 */ 2748467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles default: 275280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles dev_err(dev, "unsupported data width %u bits\n", bgc->bits); 2768467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles return -EINVAL; 2778467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles } 2788467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles 279280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles bgc->pin2mask = be ? bgpio_pin2mask_be : bgpio_pin2mask; 2808467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles 2818467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles return 0; 2828467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles} 2838467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles 284e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles/* 285e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles * Create the device and allocate the resources. For setting GPIO's there are 286dd86a0cc5e35161538c10e35eb85e2ad0adfe14dJamie Iles * three supported configurations: 287e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles * 288dd86a0cc5e35161538c10e35eb85e2ad0adfe14dJamie Iles * - single input/output register resource (named "dat"). 289e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles * - set/clear pair (named "set" and "clr"). 290dd86a0cc5e35161538c10e35eb85e2ad0adfe14dJamie Iles * - single output register resource and single input resource ("set" and 291dd86a0cc5e35161538c10e35eb85e2ad0adfe14dJamie Iles * dat"). 292e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles * 293e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles * For the single output register, this drives a 1 by setting a bit and a zero 294e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles * by clearing a bit. For the set clr pair, this drives a 1 by setting a bit 295e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles * in the set register and clears it by setting a bit in the clear register. 296e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles * The configuration is detected by which resources are present. 29731029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles * 29831029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles * For setting the GPIO direction, there are three supported configurations: 29931029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles * 30031029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles * - simple bidirection GPIO that requires no configuration. 30131029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles * - an output direction register (named "dirout") where a 1 bit 30231029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles * indicates the GPIO is an output. 30331029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles * - an input direction register (named "dirin") where a 1 bit indicates 30431029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles * the GPIO is an input. 305e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles */ 306280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Ilesstatic int bgpio_setup_io(struct bgpio_chip *bgc, 307280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles void __iomem *dat, 308280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles void __iomem *set, 309280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles void __iomem *clr) 3108467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles{ 311aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov 312280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles bgc->reg_dat = dat; 313aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov if (!bgc->reg_dat) 314280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles return -EINVAL; 315e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles 316280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles if (set && clr) { 317280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles bgc->reg_set = set; 318280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles bgc->reg_clr = clr; 319e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles bgc->gc.set = bgpio_set_with_clear; 320280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles } else if (set && !clr) { 321280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles bgc->reg_set = set; 322dd86a0cc5e35161538c10e35eb85e2ad0adfe14dJamie Iles bgc->gc.set = bgpio_set_set; 323e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles } else { 324e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles bgc->gc.set = bgpio_set; 325aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov } 326aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov 327dd86a0cc5e35161538c10e35eb85e2ad0adfe14dJamie Iles bgc->gc.get = bgpio_get; 328dd86a0cc5e35161538c10e35eb85e2ad0adfe14dJamie Iles 329e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles return 0; 330e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles} 331e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles 332280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Ilesstatic int bgpio_setup_direction(struct bgpio_chip *bgc, 333280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles void __iomem *dirout, 334280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles void __iomem *dirin) 33531029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles{ 336280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles if (dirout && dirin) { 33731029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles return -EINVAL; 338280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles } else if (dirout) { 339280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles bgc->reg_dir = dirout; 34031029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles bgc->gc.direction_output = bgpio_dir_out; 34131029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles bgc->gc.direction_input = bgpio_dir_in; 342280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles } else if (dirin) { 343280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles bgc->reg_dir = dirin; 34431029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles bgc->gc.direction_output = bgpio_dir_out_inv; 34531029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles bgc->gc.direction_input = bgpio_dir_in_inv; 34631029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles } else { 34731029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles bgc->gc.direction_output = bgpio_simple_dir_out; 34831029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles bgc->gc.direction_input = bgpio_simple_dir_in; 34931029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles } 35031029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles 35131029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles return 0; 35231029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles} 35331029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles 3544f5b04800a224aadb6cffcbbc3d3fa26e2367c7fRussell Kingint bgpio_remove(struct bgpio_chip *bgc) 355280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles{ 356280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles int err = gpiochip_remove(&bgc->gc); 357280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles 358280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles kfree(bgc); 359280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles 360280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles return err; 361280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles} 362280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie IlesEXPORT_SYMBOL_GPL(bgpio_remove); 363280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles 3644f5b04800a224aadb6cffcbbc3d3fa26e2367c7fRussell Kingint bgpio_init(struct bgpio_chip *bgc, struct device *dev, 3654f5b04800a224aadb6cffcbbc3d3fa26e2367c7fRussell King unsigned long sz, void __iomem *dat, void __iomem *set, 3664f5b04800a224aadb6cffcbbc3d3fa26e2367c7fRussell King void __iomem *clr, void __iomem *dirout, void __iomem *dirin, 3674f5b04800a224aadb6cffcbbc3d3fa26e2367c7fRussell King bool big_endian) 368e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles{ 369e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles int ret; 370e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles 371280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles if (!is_power_of_2(sz)) 372280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles return -EINVAL; 373e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles 374280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles bgc->bits = sz * 8; 375280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles if (bgc->bits > BITS_PER_LONG) 376280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles return -EINVAL; 377280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles 378280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles spin_lock_init(&bgc->lock); 379280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles bgc->gc.dev = dev; 380280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles bgc->gc.label = dev_name(dev); 381280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles bgc->gc.base = -1; 382280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles bgc->gc.ngpio = bgc->bits; 383280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles 384280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles ret = bgpio_setup_io(bgc, dat, set, clr); 385e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles if (ret) 386e027d6f9d52d9ccabb307d0cb0265de3481b1e9eJamie Iles return ret; 387aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov 388280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles ret = bgpio_setup_accessors(dev, bgc, big_endian); 3898467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles if (ret) 3908467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles return ret; 391aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov 392280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles ret = bgpio_setup_direction(bgc, dirout, dirin); 39331029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles if (ret) 39431029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles return ret; 39531029116ebc1f2481bd2380437e9f7a18f18dca5Jamie Iles 3968467afec5f8137fd0c13121f8a38c99c54c913f6Jamie Iles bgc->data = bgc->read_reg(bgc->reg_dat); 397924e7a9fc6da124588e27c611841d07047c157b4Jamie Iles 398280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles return ret; 399280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles} 400280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie IlesEXPORT_SYMBOL_GPL(bgpio_init); 401aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov 402c103de240439dfee24ac50eb99c8be3a30d13323Grant Likely#ifdef CONFIG_GPIO_GENERIC_PLATFORM 403aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov 404280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Ilesstatic void __iomem *bgpio_map(struct platform_device *pdev, 405280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles const char *name, 406280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles resource_size_t sane_sz, 407280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles int *err) 408280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles{ 409280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles struct device *dev = &pdev->dev; 410280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles struct resource *r; 411280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles resource_size_t start; 412280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles resource_size_t sz; 413280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles void __iomem *ret; 414280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles 415280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles *err = 0; 416280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles 417280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles r = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); 418280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles if (!r) 419280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles return NULL; 420280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles 421280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles sz = resource_size(r); 422280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles if (sz != sane_sz) { 423280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles *err = -EINVAL; 424280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles return NULL; 425280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles } 426280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles 427280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles start = r->start; 428280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles if (!devm_request_mem_region(dev, start, sz, r->name)) { 429280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles *err = -EBUSY; 430280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles return NULL; 431280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles } 432280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles 433280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles ret = devm_ioremap(dev, start, sz); 434280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles if (!ret) { 435280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles *err = -ENOMEM; 436280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles return NULL; 437280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles } 438aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov 439aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov return ret; 440aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov} 441aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov 442280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Ilesstatic int __devinit bgpio_pdev_probe(struct platform_device *pdev) 443280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles{ 444280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles struct device *dev = &pdev->dev; 445280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles struct resource *r; 446280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles void __iomem *dat; 447280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles void __iomem *set; 448280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles void __iomem *clr; 449280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles void __iomem *dirout; 450280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles void __iomem *dirin; 451280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles unsigned long sz; 452280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles bool be; 453280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles int err; 454280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles struct bgpio_chip *bgc; 455280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles struct bgpio_pdata *pdata = dev_get_platdata(dev); 456280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles 457280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat"); 458280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles if (!r) 459280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles return -EINVAL; 460280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles 461280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles sz = resource_size(r); 462280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles 463280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles dat = bgpio_map(pdev, "dat", sz, &err); 464280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles if (!dat) 465280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles return err ? err : -EINVAL; 466280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles 467280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles set = bgpio_map(pdev, "set", sz, &err); 468280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles if (err) 469280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles return err; 470280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles 471280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles clr = bgpio_map(pdev, "clr", sz, &err); 472280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles if (err) 473280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles return err; 474280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles 475280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles dirout = bgpio_map(pdev, "dirout", sz, &err); 476280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles if (err) 477280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles return err; 478280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles 479280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles dirin = bgpio_map(pdev, "dirin", sz, &err); 480280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles if (err) 481280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles return err; 482280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles 483280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles be = !strcmp(platform_get_device_id(pdev)->name, "basic-mmio-gpio-be"); 484280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles 485280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles bgc = devm_kzalloc(&pdev->dev, sizeof(*bgc), GFP_KERNEL); 486280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles if (!bgc) 487280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles return -ENOMEM; 488280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles 489280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles err = bgpio_init(bgc, dev, sz, dat, set, clr, dirout, dirin, be); 490280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles if (err) 491280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles return err; 492280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles 493280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles if (pdata) { 494280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles bgc->gc.base = pdata->base; 495280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles if (pdata->ngpio > 0) 496280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles bgc->gc.ngpio = pdata->ngpio; 497280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles } 498280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles 499280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles platform_set_drvdata(pdev, bgc); 500280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles 501280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles return gpiochip_add(&bgc->gc); 502280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles} 503280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles 504280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Ilesstatic int __devexit bgpio_pdev_remove(struct platform_device *pdev) 505aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov{ 5064ddb8ae217ad2aae888d00d97c5160f677dd38f4Jamie Iles struct bgpio_chip *bgc = platform_get_drvdata(pdev); 507aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov 508280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles return bgpio_remove(bgc); 509aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov} 510aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov 511aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsovstatic const struct platform_device_id bgpio_id_table[] = { 512aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov { "basic-mmio-gpio", }, 513aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov { "basic-mmio-gpio-be", }, 514aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov {}, 515aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov}; 516aeec56e331c6d2750de02ef34b305338305ca690Anton VorontsovMODULE_DEVICE_TABLE(platform, bgpio_id_table); 517aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov 518aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsovstatic struct platform_driver bgpio_driver = { 519aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov .driver = { 520aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov .name = "basic-mmio-gpio", 521aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov }, 522aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov .id_table = bgpio_id_table, 523280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles .probe = bgpio_pdev_probe, 524280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles .remove = __devexit_p(bgpio_pdev_remove), 525aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov}; 526aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov 5276f61415e9c4c0ab02c8eda7671bb652db4863cc0Mark Brownmodule_platform_driver(bgpio_driver); 528280df6b3c3ad777a91f1011cd98d50df891bfef8Jamie Iles 529c103de240439dfee24ac50eb99c8be3a30d13323Grant Likely#endif /* CONFIG_GPIO_GENERIC_PLATFORM */ 530aeec56e331c6d2750de02ef34b305338305ca690Anton Vorontsov 531aeec56e331c6d2750de02ef34b305338305ca690Anton VorontsovMODULE_DESCRIPTION("Driver for basic memory-mapped GPIO controllers"); 532aeec56e331c6d2750de02ef34b305338305ca690Anton VorontsovMODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>"); 533aeec56e331c6d2750de02ef34b305338305ca690Anton VorontsovMODULE_LICENSE("GPL"); 534