740 lines · c
1/*2 * SPEAr platform PLGPIO driver3 *4 * Copyright (C) 2012 ST Microelectronics5 * Viresh Kumar <viresh.kumar@linaro.org>6 *7 * This file is licensed under the terms of the GNU General Public8 * License version 2. This program is licensed "as is" without any9 * warranty of any kind, whether express or implied.10 */11 12#include <linux/clk.h>13#include <linux/err.h>14#include <linux/gpio/driver.h>15#include <linux/io.h>16#include <linux/init.h>17#include <linux/mfd/syscon.h>18#include <linux/of.h>19#include <linux/of_platform.h>20#include <linux/pinctrl/consumer.h>21#include <linux/platform_device.h>22#include <linux/pm.h>23#include <linux/regmap.h>24#include <linux/spinlock.h>25 26#define MAX_GPIO_PER_REG 3227#define PIN_OFFSET(pin) (pin % MAX_GPIO_PER_REG)28#define REG_OFFSET(base, reg, pin) (base + reg + (pin / MAX_GPIO_PER_REG) \29 * sizeof(int *))30 31/*32 * plgpio pins in all machines are not one to one mapped, bitwise with registers33 * bits. These set of macros define register masks for which below functions34 * (pin_to_offset and offset_to_pin) are required to be called.35 */36#define PTO_ENB_REG 0x00137#define PTO_WDATA_REG 0x00238#define PTO_DIR_REG 0x00439#define PTO_IE_REG 0x00840#define PTO_RDATA_REG 0x01041#define PTO_MIS_REG 0x02042 43struct plgpio_regs {44 u32 enb; /* enable register */45 u32 wdata; /* write data register */46 u32 dir; /* direction set register */47 u32 rdata; /* read data register */48 u32 ie; /* interrupt enable register */49 u32 mis; /* mask interrupt status register */50 u32 eit; /* edge interrupt type */51};52 53/*54 * struct plgpio: plgpio driver specific structure55 *56 * lock: lock for guarding gpio registers57 * base: base address of plgpio block58 * chip: gpio framework specific chip information structure59 * p2o: function ptr for pin to offset conversion. This is required only for60 * machines where mapping b/w pin and offset is not 1-to-1.61 * o2p: function ptr for offset to pin conversion. This is required only for62 * machines where mapping b/w pin and offset is not 1-to-1.63 * p2o_regs: mask of registers for which p2o and o2p are applicable64 * regs: register offsets65 * csave_regs: context save registers for standby/sleep/hibernate cases66 */67struct plgpio {68 spinlock_t lock;69 struct regmap *regmap;70 struct clk *clk;71 struct gpio_chip chip;72 int (*p2o)(int pin); /* pin_to_offset */73 int (*o2p)(int offset); /* offset_to_pin */74 u32 p2o_regs;75 struct plgpio_regs regs;76#ifdef CONFIG_PM_SLEEP77 struct plgpio_regs *csave_regs;78#endif79};80 81/* register manipulation inline functions */82static inline u32 is_plgpio_set(struct regmap *regmap, u32 pin, u32 reg)83{84 u32 offset = PIN_OFFSET(pin);85 u32 reg_off = REG_OFFSET(0, reg, pin);86 u32 val;87 88 regmap_read(regmap, reg_off, &val);89 90 return !!(val & (1 << offset));91}92 93static inline void plgpio_reg_set(struct regmap *regmap, u32 pin, u32 reg)94{95 u32 offset = PIN_OFFSET(pin);96 u32 reg_off = REG_OFFSET(0, reg, pin);97 u32 mask;98 99 mask = 1 << offset;100 regmap_update_bits(regmap, reg_off, mask, mask);101}102 103static inline void plgpio_reg_reset(struct regmap *regmap, u32 pin, u32 reg)104{105 u32 offset = PIN_OFFSET(pin);106 u32 reg_off = REG_OFFSET(0, reg, pin);107 u32 mask;108 109 mask = 1 << offset;110 regmap_update_bits(regmap, reg_off, mask, 0);111}112 113 114/* gpio framework specific routines */115static int plgpio_direction_input(struct gpio_chip *chip, unsigned offset)116{117 struct plgpio *plgpio = gpiochip_get_data(chip);118 unsigned long flags;119 120 /* get correct offset for "offset" pin */121 if (plgpio->p2o && (plgpio->p2o_regs & PTO_DIR_REG)) {122 offset = plgpio->p2o(offset);123 if (offset == -1)124 return -EINVAL;125 }126 127 spin_lock_irqsave(&plgpio->lock, flags);128 plgpio_reg_set(plgpio->regmap, offset, plgpio->regs.dir);129 spin_unlock_irqrestore(&plgpio->lock, flags);130 131 return 0;132}133 134static int plgpio_direction_output(struct gpio_chip *chip, unsigned offset,135 int value)136{137 struct plgpio *plgpio = gpiochip_get_data(chip);138 unsigned long flags;139 unsigned dir_offset = offset, wdata_offset = offset, tmp;140 141 /* get correct offset for "offset" pin */142 if (plgpio->p2o && (plgpio->p2o_regs & (PTO_DIR_REG | PTO_WDATA_REG))) {143 tmp = plgpio->p2o(offset);144 if (tmp == -1)145 return -EINVAL;146 147 if (plgpio->p2o_regs & PTO_DIR_REG)148 dir_offset = tmp;149 if (plgpio->p2o_regs & PTO_WDATA_REG)150 wdata_offset = tmp;151 }152 153 spin_lock_irqsave(&plgpio->lock, flags);154 if (value)155 plgpio_reg_set(plgpio->regmap, wdata_offset,156 plgpio->regs.wdata);157 else158 plgpio_reg_reset(plgpio->regmap, wdata_offset,159 plgpio->regs.wdata);160 161 plgpio_reg_reset(plgpio->regmap, dir_offset, plgpio->regs.dir);162 spin_unlock_irqrestore(&plgpio->lock, flags);163 164 return 0;165}166 167static int plgpio_get_value(struct gpio_chip *chip, unsigned offset)168{169 struct plgpio *plgpio = gpiochip_get_data(chip);170 171 if (offset >= chip->ngpio)172 return -EINVAL;173 174 /* get correct offset for "offset" pin */175 if (plgpio->p2o && (plgpio->p2o_regs & PTO_RDATA_REG)) {176 offset = plgpio->p2o(offset);177 if (offset == -1)178 return -EINVAL;179 }180 181 return is_plgpio_set(plgpio->regmap, offset, plgpio->regs.rdata);182}183 184static void plgpio_set_value(struct gpio_chip *chip, unsigned offset, int value)185{186 struct plgpio *plgpio = gpiochip_get_data(chip);187 188 if (offset >= chip->ngpio)189 return;190 191 /* get correct offset for "offset" pin */192 if (plgpio->p2o && (plgpio->p2o_regs & PTO_WDATA_REG)) {193 offset = plgpio->p2o(offset);194 if (offset == -1)195 return;196 }197 198 if (value)199 plgpio_reg_set(plgpio->regmap, offset, plgpio->regs.wdata);200 else201 plgpio_reg_reset(plgpio->regmap, offset, plgpio->regs.wdata);202}203 204static int plgpio_request(struct gpio_chip *chip, unsigned offset)205{206 struct plgpio *plgpio = gpiochip_get_data(chip);207 unsigned long flags;208 int ret = 0;209 210 if (offset >= chip->ngpio)211 return -EINVAL;212 213 ret = pinctrl_gpio_request(chip, offset);214 if (ret)215 return ret;216 217 if (!IS_ERR(plgpio->clk)) {218 ret = clk_enable(plgpio->clk);219 if (ret)220 goto err0;221 }222 223 if (plgpio->regs.enb == -1)224 return 0;225 226 /*227 * put gpio in IN mode before enabling it. This make enabling gpio safe228 */229 ret = plgpio_direction_input(chip, offset);230 if (ret)231 goto err1;232 233 /* get correct offset for "offset" pin */234 if (plgpio->p2o && (plgpio->p2o_regs & PTO_ENB_REG)) {235 offset = plgpio->p2o(offset);236 if (offset == -1) {237 ret = -EINVAL;238 goto err1;239 }240 }241 242 spin_lock_irqsave(&plgpio->lock, flags);243 plgpio_reg_set(plgpio->regmap, offset, plgpio->regs.enb);244 spin_unlock_irqrestore(&plgpio->lock, flags);245 return 0;246 247err1:248 if (!IS_ERR(plgpio->clk))249 clk_disable(plgpio->clk);250err0:251 pinctrl_gpio_free(chip, offset);252 return ret;253}254 255static void plgpio_free(struct gpio_chip *chip, unsigned offset)256{257 struct plgpio *plgpio = gpiochip_get_data(chip);258 unsigned long flags;259 260 if (offset >= chip->ngpio)261 return;262 263 if (plgpio->regs.enb == -1)264 goto disable_clk;265 266 /* get correct offset for "offset" pin */267 if (plgpio->p2o && (plgpio->p2o_regs & PTO_ENB_REG)) {268 offset = plgpio->p2o(offset);269 if (offset == -1)270 return;271 }272 273 spin_lock_irqsave(&plgpio->lock, flags);274 plgpio_reg_reset(plgpio->regmap, offset, plgpio->regs.enb);275 spin_unlock_irqrestore(&plgpio->lock, flags);276 277disable_clk:278 if (!IS_ERR(plgpio->clk))279 clk_disable(plgpio->clk);280 281 pinctrl_gpio_free(chip, offset);282}283 284/* PLGPIO IRQ */285static void plgpio_irq_disable(struct irq_data *d)286{287 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);288 struct plgpio *plgpio = gpiochip_get_data(gc);289 int offset = d->hwirq;290 unsigned long flags;291 292 /* get correct offset for "offset" pin */293 if (plgpio->p2o && (plgpio->p2o_regs & PTO_IE_REG)) {294 offset = plgpio->p2o(offset);295 if (offset == -1)296 return;297 }298 299 spin_lock_irqsave(&plgpio->lock, flags);300 plgpio_reg_set(plgpio->regmap, offset, plgpio->regs.ie);301 spin_unlock_irqrestore(&plgpio->lock, flags);302 gpiochip_disable_irq(gc, irqd_to_hwirq(d));303}304 305static void plgpio_irq_enable(struct irq_data *d)306{307 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);308 struct plgpio *plgpio = gpiochip_get_data(gc);309 int offset = d->hwirq;310 unsigned long flags;311 312 /* get correct offset for "offset" pin */313 if (plgpio->p2o && (plgpio->p2o_regs & PTO_IE_REG)) {314 offset = plgpio->p2o(offset);315 if (offset == -1)316 return;317 }318 319 gpiochip_enable_irq(gc, irqd_to_hwirq(d));320 spin_lock_irqsave(&plgpio->lock, flags);321 plgpio_reg_reset(plgpio->regmap, offset, plgpio->regs.ie);322 spin_unlock_irqrestore(&plgpio->lock, flags);323}324 325static int plgpio_irq_set_type(struct irq_data *d, unsigned trigger)326{327 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);328 struct plgpio *plgpio = gpiochip_get_data(gc);329 int offset = d->hwirq;330 u32 reg_off;331 unsigned int supported_type = 0, val;332 333 if (offset >= plgpio->chip.ngpio)334 return -EINVAL;335 336 if (plgpio->regs.eit == -1)337 supported_type = IRQ_TYPE_LEVEL_HIGH;338 else339 supported_type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;340 341 if (!(trigger & supported_type))342 return -EINVAL;343 344 if (plgpio->regs.eit == -1)345 return 0;346 347 reg_off = REG_OFFSET(0, plgpio->regs.eit, offset);348 regmap_read(plgpio->regmap, reg_off, &val);349 350 offset = PIN_OFFSET(offset);351 if (trigger & IRQ_TYPE_EDGE_RISING)352 regmap_write(plgpio->regmap, reg_off, val | (1 << offset));353 else354 regmap_write(plgpio->regmap, reg_off, val & ~(1 << offset));355 356 return 0;357}358 359static const struct irq_chip plgpio_irqchip = {360 .name = "PLGPIO",361 .irq_enable = plgpio_irq_enable,362 .irq_disable = plgpio_irq_disable,363 .irq_set_type = plgpio_irq_set_type,364 .flags = IRQCHIP_IMMUTABLE,365 GPIOCHIP_IRQ_RESOURCE_HELPERS,366};367 368static void plgpio_irq_handler(struct irq_desc *desc)369{370 struct gpio_chip *gc = irq_desc_get_handler_data(desc);371 struct plgpio *plgpio = gpiochip_get_data(gc);372 struct irq_chip *irqchip = irq_desc_get_chip(desc);373 int regs_count, count, pin, offset, i = 0;374 u32 pending;375 unsigned long pendingl;376 377 count = plgpio->chip.ngpio;378 regs_count = DIV_ROUND_UP(count, MAX_GPIO_PER_REG);379 380 chained_irq_enter(irqchip, desc);381 /* check all plgpio MIS registers for a possible interrupt */382 for (; i < regs_count; i++) {383 regmap_read(plgpio->regmap, plgpio->regs.mis +384 i * sizeof(int *), &pending);385 if (!pending)386 continue;387 388 /* clear interrupts */389 regmap_write(plgpio->regmap, plgpio->regs.mis +390 i * sizeof(int *), ~pending);391 /*392 * clear extra bits in last register having gpios < MAX/REG393 * ex: Suppose there are max 102 plgpios. then last register394 * must have only (102 - MAX_GPIO_PER_REG * 3) = 6 relevant bits395 * so, we must not take other 28 bits into consideration for396 * checking interrupt. so clear those bits.397 */398 count = count - i * MAX_GPIO_PER_REG;399 if (count < MAX_GPIO_PER_REG)400 pending &= (1 << count) - 1;401 402 pendingl = pending;403 for_each_set_bit(offset, &pendingl, MAX_GPIO_PER_REG) {404 /* get correct pin for "offset" */405 if (plgpio->o2p && (plgpio->p2o_regs & PTO_MIS_REG)) {406 pin = plgpio->o2p(offset);407 if (pin == -1)408 continue;409 } else410 pin = offset;411 412 /* get correct irq line number */413 pin = i * MAX_GPIO_PER_REG + pin;414 generic_handle_domain_irq(gc->irq.domain, pin);415 }416 }417 chained_irq_exit(irqchip, desc);418}419 420/*421 * pin to offset and offset to pin converter functions422 *423 * In spear310 there is inconsistency among bit positions in plgpio regiseters,424 * for different plgpio pins. For example: for pin 27, bit offset is 23, pin425 * 28-33 are not supported, pin 95 has offset bit 95, bit 100 has offset bit 1426 */427static int spear310_p2o(int pin)428{429 int offset = pin;430 431 if (pin <= 27)432 offset += 4;433 else if (pin <= 33)434 offset = -1;435 else if (pin <= 97)436 offset -= 2;437 else if (pin <= 101)438 offset = 101 - pin;439 else440 offset = -1;441 442 return offset;443}444 445static int spear310_o2p(int offset)446{447 if (offset <= 3)448 return 101 - offset;449 else if (offset <= 31)450 return offset - 4;451 else452 return offset + 2;453}454 455static int plgpio_probe_dt(struct platform_device *pdev, struct plgpio *plgpio)456{457 struct device_node *np = pdev->dev.of_node;458 int ret = -EINVAL;459 u32 val;460 461 if (of_machine_is_compatible("st,spear310")) {462 plgpio->p2o = spear310_p2o;463 plgpio->o2p = spear310_o2p;464 plgpio->p2o_regs = PTO_WDATA_REG | PTO_DIR_REG | PTO_IE_REG |465 PTO_RDATA_REG | PTO_MIS_REG;466 }467 468 if (!of_property_read_u32(np, "st-plgpio,ngpio", &val)) {469 plgpio->chip.ngpio = val;470 } else {471 dev_err(&pdev->dev, "DT: Invalid ngpio field\n");472 goto end;473 }474 475 if (!of_property_read_u32(np, "st-plgpio,enb-reg", &val))476 plgpio->regs.enb = val;477 else478 plgpio->regs.enb = -1;479 480 if (!of_property_read_u32(np, "st-plgpio,wdata-reg", &val)) {481 plgpio->regs.wdata = val;482 } else {483 dev_err(&pdev->dev, "DT: Invalid wdata reg\n");484 goto end;485 }486 487 if (!of_property_read_u32(np, "st-plgpio,dir-reg", &val)) {488 plgpio->regs.dir = val;489 } else {490 dev_err(&pdev->dev, "DT: Invalid dir reg\n");491 goto end;492 }493 494 if (!of_property_read_u32(np, "st-plgpio,ie-reg", &val)) {495 plgpio->regs.ie = val;496 } else {497 dev_err(&pdev->dev, "DT: Invalid ie reg\n");498 goto end;499 }500 501 if (!of_property_read_u32(np, "st-plgpio,rdata-reg", &val)) {502 plgpio->regs.rdata = val;503 } else {504 dev_err(&pdev->dev, "DT: Invalid rdata reg\n");505 goto end;506 }507 508 if (!of_property_read_u32(np, "st-plgpio,mis-reg", &val)) {509 plgpio->regs.mis = val;510 } else {511 dev_err(&pdev->dev, "DT: Invalid mis reg\n");512 goto end;513 }514 515 if (!of_property_read_u32(np, "st-plgpio,eit-reg", &val))516 plgpio->regs.eit = val;517 else518 plgpio->regs.eit = -1;519 520 return 0;521 522end:523 return ret;524}525 526static int plgpio_probe(struct platform_device *pdev)527{528 struct device_node *regmap_np;529 struct plgpio *plgpio;530 int ret, irq;531 532 plgpio = devm_kzalloc(&pdev->dev, sizeof(*plgpio), GFP_KERNEL);533 if (!plgpio)534 return -ENOMEM;535 536 regmap_np = of_parse_phandle(pdev->dev.of_node, "regmap", 0);537 if (regmap_np) {538 plgpio->regmap = device_node_to_regmap(regmap_np);539 of_node_put(regmap_np);540 if (IS_ERR(plgpio->regmap)) {541 dev_err(&pdev->dev, "Retrieve regmap failed (%pe)\n",542 plgpio->regmap);543 return PTR_ERR(plgpio->regmap);544 }545 } else {546 plgpio->regmap = device_node_to_regmap(pdev->dev.of_node);547 if (IS_ERR(plgpio->regmap)) {548 dev_err(&pdev->dev, "Init regmap failed (%pe)\n",549 plgpio->regmap);550 return PTR_ERR(plgpio->regmap);551 }552 }553 554 ret = plgpio_probe_dt(pdev, plgpio);555 if (ret) {556 dev_err(&pdev->dev, "DT probe failed\n");557 return ret;558 }559 560 plgpio->clk = devm_clk_get(&pdev->dev, NULL);561 if (IS_ERR(plgpio->clk))562 dev_warn(&pdev->dev, "clk_get() failed, work without it\n");563 564#ifdef CONFIG_PM_SLEEP565 plgpio->csave_regs = devm_kcalloc(&pdev->dev,566 DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG),567 sizeof(*plgpio->csave_regs),568 GFP_KERNEL);569 if (!plgpio->csave_regs)570 return -ENOMEM;571#endif572 573 platform_set_drvdata(pdev, plgpio);574 spin_lock_init(&plgpio->lock);575 576 plgpio->chip.base = -1;577 plgpio->chip.request = plgpio_request;578 plgpio->chip.free = plgpio_free;579 plgpio->chip.direction_input = plgpio_direction_input;580 plgpio->chip.direction_output = plgpio_direction_output;581 plgpio->chip.get = plgpio_get_value;582 plgpio->chip.set = plgpio_set_value;583 plgpio->chip.label = dev_name(&pdev->dev);584 plgpio->chip.parent = &pdev->dev;585 plgpio->chip.owner = THIS_MODULE;586 587 if (!IS_ERR(plgpio->clk)) {588 ret = clk_prepare(plgpio->clk);589 if (ret) {590 dev_err(&pdev->dev, "clk prepare failed\n");591 return ret;592 }593 }594 595 irq = platform_get_irq(pdev, 0);596 if (irq > 0) {597 struct gpio_irq_chip *girq;598 599 girq = &plgpio->chip.irq;600 gpio_irq_chip_set_chip(girq, &plgpio_irqchip);601 girq->parent_handler = plgpio_irq_handler;602 girq->num_parents = 1;603 girq->parents = devm_kcalloc(&pdev->dev, 1,604 sizeof(*girq->parents),605 GFP_KERNEL);606 if (!girq->parents)607 return -ENOMEM;608 girq->parents[0] = irq;609 girq->default_type = IRQ_TYPE_NONE;610 girq->handler = handle_simple_irq;611 dev_info(&pdev->dev, "PLGPIO registering with IRQs\n");612 } else {613 dev_info(&pdev->dev, "PLGPIO registering without IRQs\n");614 }615 616 ret = gpiochip_add_data(&plgpio->chip, plgpio);617 if (ret) {618 dev_err(&pdev->dev, "unable to add gpio chip\n");619 goto unprepare_clk;620 }621 622 return 0;623 624unprepare_clk:625 if (!IS_ERR(plgpio->clk))626 clk_unprepare(plgpio->clk);627 628 return ret;629}630 631#ifdef CONFIG_PM_SLEEP632static int plgpio_suspend(struct device *dev)633{634 struct plgpio *plgpio = dev_get_drvdata(dev);635 int i, reg_count = DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG);636 u32 off;637 638 for (i = 0; i < reg_count; i++) {639 off = i * sizeof(int *);640 641 if (plgpio->regs.enb != -1)642 regmap_read(plgpio->regmap, plgpio->regs.enb + off,643 &plgpio->csave_regs[i].enb);644 if (plgpio->regs.eit != -1)645 regmap_read(plgpio->regmap, plgpio->regs.eit + off,646 &plgpio->csave_regs[i].eit);647 regmap_read(plgpio->regmap, plgpio->regs.wdata + off,648 &plgpio->csave_regs[i].wdata);649 regmap_read(plgpio->regmap, plgpio->regs.dir + off,650 &plgpio->csave_regs[i].dir);651 regmap_read(plgpio->regmap, plgpio->regs.ie + off,652 &plgpio->csave_regs[i].ie);653 }654 655 return 0;656}657 658/*659 * This is used to correct the values in end registers. End registers contain660 * extra bits that might be used for other purpose in platform. So, we shouldn't661 * overwrite these bits. This macro, reads given register again, preserves other662 * bit values (non-plgpio bits), and retain captured value (plgpio bits).663 */664#define plgpio_prepare_reg(__reg, _off, _mask, _tmp) \665{ \666 regmap_read(plgpio->regmap, plgpio->regs.__reg + _off, &_tmp); \667 _tmp &= ~_mask; \668 plgpio->csave_regs[i].__reg = \669 _tmp | (plgpio->csave_regs[i].__reg & _mask); \670}671 672static int plgpio_resume(struct device *dev)673{674 struct plgpio *plgpio = dev_get_drvdata(dev);675 int i, reg_count = DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG);676 u32 off;677 u32 mask, tmp;678 679 for (i = 0; i < reg_count; i++) {680 off = i * sizeof(int *);681 682 if (i == reg_count - 1) {683 mask = (1 << (plgpio->chip.ngpio - i *684 MAX_GPIO_PER_REG)) - 1;685 686 if (plgpio->regs.enb != -1)687 plgpio_prepare_reg(enb, off, mask, tmp);688 689 if (plgpio->regs.eit != -1)690 plgpio_prepare_reg(eit, off, mask, tmp);691 692 plgpio_prepare_reg(wdata, off, mask, tmp);693 plgpio_prepare_reg(dir, off, mask, tmp);694 plgpio_prepare_reg(ie, off, mask, tmp);695 }696 697 regmap_write(plgpio->regmap, plgpio->regs.wdata + off,698 plgpio->csave_regs[i].wdata);699 700 regmap_write(plgpio->regmap, plgpio->regs.dir + off,701 plgpio->csave_regs[i].dir);702 703 if (plgpio->regs.eit != -1)704 regmap_write(plgpio->regmap, plgpio->regs.eit + off,705 plgpio->csave_regs[i].eit);706 707 regmap_write(plgpio->regmap, plgpio->regs.ie + off,708 plgpio->csave_regs[i].ie);709 710 if (plgpio->regs.enb != -1)711 regmap_write(plgpio->regmap, plgpio->regs.enb + off,712 plgpio->csave_regs[i].enb);713 }714 715 return 0;716}717#endif718 719static SIMPLE_DEV_PM_OPS(plgpio_dev_pm_ops, plgpio_suspend, plgpio_resume);720 721static const struct of_device_id plgpio_of_match[] = {722 { .compatible = "st,spear-plgpio" },723 {}724};725 726static struct platform_driver plgpio_driver = {727 .probe = plgpio_probe,728 .driver = {729 .name = "spear-plgpio",730 .pm = &plgpio_dev_pm_ops,731 .of_match_table = plgpio_of_match,732 },733};734 735static int __init plgpio_init(void)736{737 return platform_driver_register(&plgpio_driver);738}739subsys_initcall(plgpio_init);740