brintos

brintos / linux-shallow public Read only

0
0
Text · 7.7 KiB · e85af7f Raw
313 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/* NXP PCF50633 Power Management Unit (PMU) driver3 *4 * (C) 2006-2008 by Openmoko, Inc.5 * Author: Harald Welte <laforge@openmoko.org>6 * 	   Balaji Rao <balajirrao@openmoko.org>7 * All rights reserved.8 */9 10#include <linux/i2c.h>11#include <linux/interrupt.h>12#include <linux/kernel.h>13#include <linux/mutex.h>14#include <linux/export.h>15#include <linux/slab.h>16 17#include <linux/mfd/pcf50633/core.h>18#include <linux/mfd/pcf50633/mbc.h>19 20int pcf50633_register_irq(struct pcf50633 *pcf, int irq,21			void (*handler) (int, void *), void *data)22{23	if (irq < 0 || irq >= PCF50633_NUM_IRQ || !handler)24		return -EINVAL;25 26	if (WARN_ON(pcf->irq_handler[irq].handler))27		return -EBUSY;28 29	mutex_lock(&pcf->lock);30	pcf->irq_handler[irq].handler = handler;31	pcf->irq_handler[irq].data = data;32	mutex_unlock(&pcf->lock);33 34	return 0;35}36EXPORT_SYMBOL_GPL(pcf50633_register_irq);37 38int pcf50633_free_irq(struct pcf50633 *pcf, int irq)39{40	if (irq < 0 || irq >= PCF50633_NUM_IRQ)41		return -EINVAL;42 43	mutex_lock(&pcf->lock);44	pcf->irq_handler[irq].handler = NULL;45	mutex_unlock(&pcf->lock);46 47	return 0;48}49EXPORT_SYMBOL_GPL(pcf50633_free_irq);50 51static int __pcf50633_irq_mask_set(struct pcf50633 *pcf, int irq, u8 mask)52{53	u8 reg, bit;54	int idx;55 56	idx = irq >> 3;57	reg = PCF50633_REG_INT1M + idx;58	bit = 1 << (irq & 0x07);59 60	pcf50633_reg_set_bit_mask(pcf, reg, bit, mask ? bit : 0);61 62	mutex_lock(&pcf->lock);63 64	if (mask)65		pcf->mask_regs[idx] |= bit;66	else67		pcf->mask_regs[idx] &= ~bit;68 69	mutex_unlock(&pcf->lock);70 71	return 0;72}73 74int pcf50633_irq_mask(struct pcf50633 *pcf, int irq)75{76	dev_dbg(pcf->dev, "Masking IRQ %d\n", irq);77 78	return __pcf50633_irq_mask_set(pcf, irq, 1);79}80EXPORT_SYMBOL_GPL(pcf50633_irq_mask);81 82int pcf50633_irq_unmask(struct pcf50633 *pcf, int irq)83{84	dev_dbg(pcf->dev, "Unmasking IRQ %d\n", irq);85 86	return __pcf50633_irq_mask_set(pcf, irq, 0);87}88EXPORT_SYMBOL_GPL(pcf50633_irq_unmask);89 90int pcf50633_irq_mask_get(struct pcf50633 *pcf, int irq)91{92	u8 reg, bits;93 94	reg =  irq >> 3;95	bits = 1 << (irq & 0x07);96 97	return pcf->mask_regs[reg] & bits;98}99EXPORT_SYMBOL_GPL(pcf50633_irq_mask_get);100 101static void pcf50633_irq_call_handler(struct pcf50633 *pcf, int irq)102{103	if (pcf->irq_handler[irq].handler)104		pcf->irq_handler[irq].handler(irq, pcf->irq_handler[irq].data);105}106 107/* Maximum amount of time ONKEY is held before emergency action is taken */108#define PCF50633_ONKEY1S_TIMEOUT 8109 110static irqreturn_t pcf50633_irq(int irq, void *data)111{112	struct pcf50633 *pcf = data;113	int ret, i, j;114	u8 pcf_int[5], chgstat;115 116	/* Read the 5 INT regs in one transaction */117	ret = pcf50633_read_block(pcf, PCF50633_REG_INT1,118						ARRAY_SIZE(pcf_int), pcf_int);119	if (ret != ARRAY_SIZE(pcf_int)) {120		dev_err(pcf->dev, "Error reading INT registers\n");121 122		/*123		 * If this doesn't ACK the interrupt to the chip, we'll be124		 * called once again as we're level triggered.125		 */126		goto out;127	}128 129	/* defeat 8s death from lowsys on A5 */130	pcf50633_reg_write(pcf, PCF50633_REG_OOCSHDWN,  0x04);131 132	/* We immediately read the usb and adapter status. We thus make sure133	 * only of USBINS/USBREM IRQ handlers are called */134	if (pcf_int[0] & (PCF50633_INT1_USBINS | PCF50633_INT1_USBREM)) {135		chgstat = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2);136		if (chgstat & (0x3 << 4))137			pcf_int[0] &= ~PCF50633_INT1_USBREM;138		else139			pcf_int[0] &= ~PCF50633_INT1_USBINS;140	}141 142	/* Make sure only one of ADPINS or ADPREM is set */143	if (pcf_int[0] & (PCF50633_INT1_ADPINS | PCF50633_INT1_ADPREM)) {144		chgstat = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2);145		if (chgstat & (0x3 << 4))146			pcf_int[0] &= ~PCF50633_INT1_ADPREM;147		else148			pcf_int[0] &= ~PCF50633_INT1_ADPINS;149	}150 151	dev_dbg(pcf->dev, "INT1=0x%02x INT2=0x%02x INT3=0x%02x "152			"INT4=0x%02x INT5=0x%02x\n", pcf_int[0],153			pcf_int[1], pcf_int[2], pcf_int[3], pcf_int[4]);154 155	/* Some revisions of the chip don't have a 8s standby mode on156	 * ONKEY1S press. We try to manually do it in such cases. */157	if ((pcf_int[0] & PCF50633_INT1_SECOND) && pcf->onkey1s_held) {158		dev_info(pcf->dev, "ONKEY1S held for %d secs\n",159							pcf->onkey1s_held);160		if (pcf->onkey1s_held++ == PCF50633_ONKEY1S_TIMEOUT)161			if (pcf->pdata->force_shutdown)162				pcf->pdata->force_shutdown(pcf);163	}164 165	if (pcf_int[2] & PCF50633_INT3_ONKEY1S) {166		dev_info(pcf->dev, "ONKEY1S held\n");167		pcf->onkey1s_held = 1 ;168 169		/* Unmask IRQ_SECOND */170		pcf50633_reg_clear_bits(pcf, PCF50633_REG_INT1M,171						PCF50633_INT1_SECOND);172 173		/* Unmask IRQ_ONKEYR */174		pcf50633_reg_clear_bits(pcf, PCF50633_REG_INT2M,175						PCF50633_INT2_ONKEYR);176	}177 178	if ((pcf_int[1] & PCF50633_INT2_ONKEYR) && pcf->onkey1s_held) {179		pcf->onkey1s_held = 0;180 181		/* Mask SECOND and ONKEYR interrupts */182		if (pcf->mask_regs[0] & PCF50633_INT1_SECOND)183			pcf50633_reg_set_bit_mask(pcf,184					PCF50633_REG_INT1M,185					PCF50633_INT1_SECOND,186					PCF50633_INT1_SECOND);187 188		if (pcf->mask_regs[1] & PCF50633_INT2_ONKEYR)189			pcf50633_reg_set_bit_mask(pcf,190					PCF50633_REG_INT2M,191					PCF50633_INT2_ONKEYR,192					PCF50633_INT2_ONKEYR);193	}194 195	/* Have we just resumed ? */196	if (pcf->is_suspended) {197		pcf->is_suspended = 0;198 199		/* Set the resume reason filtering out non resumers */200		for (i = 0; i < ARRAY_SIZE(pcf_int); i++)201			pcf->resume_reason[i] = pcf_int[i] &202						pcf->pdata->resumers[i];203 204		/* Make sure we don't pass on any ONKEY events to205		 * userspace now */206		pcf_int[1] &= ~(PCF50633_INT2_ONKEYR | PCF50633_INT2_ONKEYF);207	}208 209	for (i = 0; i < ARRAY_SIZE(pcf_int); i++) {210		/* Unset masked interrupts */211		pcf_int[i] &= ~pcf->mask_regs[i];212 213		for (j = 0; j < 8 ; j++)214			if (pcf_int[i] & (1 << j))215				pcf50633_irq_call_handler(pcf, (i * 8) + j);216	}217 218out:219	return IRQ_HANDLED;220}221 222static int pcf50633_suspend(struct device *dev)223{224	struct i2c_client *client = to_i2c_client(dev);225	struct pcf50633 *pcf = i2c_get_clientdata(client);226	int ret;227	int i;228	u8 res[5];229 230 231	/* Make sure our interrupt handlers are not called232	 * henceforth */233	disable_irq(pcf->irq);234 235	/* Save the masks */236	ret = pcf50633_read_block(pcf, PCF50633_REG_INT1M,237				ARRAY_SIZE(pcf->suspend_irq_masks),238					pcf->suspend_irq_masks);239	if (ret < 0) {240		dev_err(pcf->dev, "error saving irq masks\n");241		goto out;242	}243 244	/* Write wakeup irq masks */245	for (i = 0; i < ARRAY_SIZE(res); i++)246		res[i] = ~pcf->pdata->resumers[i];247 248	ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M,249					ARRAY_SIZE(res), &res[0]);250	if (ret < 0) {251		dev_err(pcf->dev, "error writing wakeup irq masks\n");252		goto out;253	}254 255	pcf->is_suspended = 1;256 257out:258	return ret;259}260 261static int pcf50633_resume(struct device *dev)262{263	struct i2c_client *client = to_i2c_client(dev);264	struct pcf50633 *pcf = i2c_get_clientdata(client);265	int ret;266 267	/* Write the saved mask registers */268	ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M,269				ARRAY_SIZE(pcf->suspend_irq_masks),270					pcf->suspend_irq_masks);271	if (ret < 0)272		dev_err(pcf->dev, "Error restoring saved suspend masks\n");273 274	enable_irq(pcf->irq);275 276	return ret;277}278 279EXPORT_GPL_SIMPLE_DEV_PM_OPS(pcf50633_pm, pcf50633_suspend, pcf50633_resume);280 281int pcf50633_irq_init(struct pcf50633 *pcf, int irq)282{283	int ret;284 285	pcf->irq = irq;286 287	/* Enable all interrupts except RTC SECOND */288	pcf->mask_regs[0] = 0x80;289	pcf50633_reg_write(pcf, PCF50633_REG_INT1M, pcf->mask_regs[0]);290	pcf50633_reg_write(pcf, PCF50633_REG_INT2M, 0x00);291	pcf50633_reg_write(pcf, PCF50633_REG_INT3M, 0x00);292	pcf50633_reg_write(pcf, PCF50633_REG_INT4M, 0x00);293	pcf50633_reg_write(pcf, PCF50633_REG_INT5M, 0x00);294 295	ret = request_threaded_irq(irq, NULL, pcf50633_irq,296					IRQF_TRIGGER_LOW | IRQF_ONESHOT,297					"pcf50633", pcf);298 299	if (ret)300		dev_err(pcf->dev, "Failed to request IRQ %d\n", ret);301 302	if (enable_irq_wake(irq) < 0)303		dev_err(pcf->dev, "IRQ %u cannot be enabled as wake-up source"304			"in this hardware revision", irq);305 306	return ret;307}308 309void pcf50633_irq_free(struct pcf50633 *pcf)310{311	free_irq(pcf->irq, pcf);312}313