brintos

brintos / linux-shallow public Read only

0
0
Text · 18.6 KiB · a05570c Raw
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