static irqreturn_t button_irq(int irq, void *_priv) { struct mc13783_pwrb *priv = _priv; int val; mc13xxx_irq_ack(priv->mc13783, irq); mc13xxx_reg_read(priv->mc13783, MC13783_REG_INTERRUPT_SENSE_1, &val); switch (irq) { case MC13783_IRQ_ONOFD1: val = val & MC13783_IRQSENSE1_ONOFD1S ? 1 : 0; if (priv->flags & MC13783_PWRB_B1_POL_INVERT) val ^= 1; input_report_key(priv->pwr, priv->keymap[0], val); break; case MC13783_IRQ_ONOFD2: val = val & MC13783_IRQSENSE1_ONOFD2S ? 1 : 0; if (priv->flags & MC13783_PWRB_B2_POL_INVERT) val ^= 1; input_report_key(priv->pwr, priv->keymap[1], val); break; case MC13783_IRQ_ONOFD3: val = val & MC13783_IRQSENSE1_ONOFD3S ? 1 : 0; if (priv->flags & MC13783_PWRB_B3_POL_INVERT) val ^= 1; input_report_key(priv->pwr, priv->keymap[2], val); break; } input_sync(priv->pwr); return IRQ_HANDLED; }
static irqreturn_t mc13xxx_handler_adcdone(int irq, void *data) { struct mc13xxx_adcdone_data *adcdone_data = data; mc13xxx_irq_ack(adcdone_data->mc13xxx, irq); complete_all(&adcdone_data->done); return IRQ_HANDLED; }
static irqreturn_t mc13xxx_rtc_alarm_handler(int irq, void *dev) { struct mc13xxx_rtc *priv = dev; struct mc13xxx *mc13xxx = priv->mc13xxx; rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_AF); mc13xxx_irq_ack(mc13xxx, irq); return IRQ_HANDLED; }
static irqreturn_t mc13xxx_rtc_update_handler(int irq, void *dev) { struct mc13xxx_rtc *priv = dev; struct mc13xxx *mc13xxx = priv->mc13xxx; dev_dbg(&priv->rtc->dev, "1HZ\n"); rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_UF); mc13xxx_irq_ack(mc13xxx, irq); return IRQ_HANDLED; }
static int __init mc13xxx_rtc_probe(struct platform_device *pdev) { int ret; struct mc13xxx_rtc *priv; struct mc13xxx *mc13xxx; priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; mc13xxx = dev_get_drvdata(pdev->dev.parent); priv->mc13xxx = mc13xxx; priv->valid = 1; platform_set_drvdata(pdev, priv); mc13xxx_lock(mc13xxx); mc13xxx_irq_ack(mc13xxx, MC13XXX_IRQ_RTCRST); ret = mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_RTCRST, mc13xxx_rtc_reset_handler, DRIVER_NAME, priv); if (ret) goto err_irq_request; ret = mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_1HZ, mc13xxx_rtc_update_handler, DRIVER_NAME, priv); if (ret) goto err_irq_request; ret = mc13xxx_irq_request_nounmask(mc13xxx, MC13XXX_IRQ_TODA, mc13xxx_rtc_alarm_handler, DRIVER_NAME, priv); if (ret) goto err_irq_request; mc13xxx_unlock(mc13xxx); priv->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &mc13xxx_rtc_ops, THIS_MODULE); return 0; err_irq_request: mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_TODA, priv); mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_1HZ, priv); mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_RTCRST, priv); mc13xxx_unlock(mc13xxx); return ret; }
static int mc13xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) { struct mc13xxx_rtc *priv = dev_get_drvdata(dev); unsigned long s1970; unsigned seconds, days; int ret; mc13xxx_lock(priv->mc13xxx); /* */ ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTODA, 0x1ffff); if (unlikely(ret)) goto out; ret = mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_TODA); if (unlikely(ret)) goto out; ret = rtc_tm_to_time(&alarm->time, &s1970); if (unlikely(ret)) goto out; dev_dbg(dev, "%s: o%2.s %lu\n", __func__, alarm->enabled ? "n" : "ff", s1970); ret = mc13xxx_rtc_irq_enable_unlocked(dev, alarm->enabled, MC13XXX_IRQ_TODA); if (unlikely(ret)) goto out; seconds = s1970 % 86400; days = s1970 / 86400; ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCDAYA, days); if (unlikely(ret)) goto out; ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTODA, seconds); out: mc13xxx_unlock(priv->mc13xxx); return ret; }
static int mc13xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) { struct mc13xxx_rtc *priv = dev_get_drvdata(dev); time64_t s1970; u32 seconds, days; int ret; mc13xxx_lock(priv->mc13xxx); /* disable alarm to prevent false triggering */ ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTODA, 0x1ffff); if (unlikely(ret)) goto out; ret = mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_TODA); if (unlikely(ret)) goto out; s1970 = rtc_tm_to_time64(&alarm->time); dev_dbg(dev, "%s: %s %lld\n", __func__, alarm->enabled ? "on" : "off", (long long)s1970); ret = mc13xxx_rtc_irq_enable_unlocked(dev, alarm->enabled, MC13XXX_IRQ_TODA); if (unlikely(ret)) goto out; days = div_s64_rem(s1970, SEC_PER_DAY, &seconds); ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCDAYA, days); if (unlikely(ret)) goto out; ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTODA, seconds); out: mc13xxx_unlock(priv->mc13xxx); return ret; }
static int mc13xxx_rtc_set_mmss(struct device *dev, unsigned long secs) { struct mc13xxx_rtc *priv = dev_get_drvdata(dev); unsigned int seconds, days; unsigned int alarmseconds; int ret; seconds = secs % 86400; days = secs / 86400; mc13xxx_lock(priv->mc13xxx); /* */ ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTODA, &alarmseconds); if (unlikely(ret)) goto out; if (alarmseconds < 86400) { ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTODA, 0x1ffff); if (unlikely(ret)) goto out; } /* */ ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTOD, 0); if (unlikely(ret)) goto out; ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCDAY, days); if (unlikely(ret)) goto out; ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTOD, seconds); if (unlikely(ret)) goto out; /* */ if (alarmseconds < 86400) { ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTODA, alarmseconds); if (unlikely(ret)) goto out; } ret = mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_RTCRST); if (unlikely(ret)) goto out; ret = mc13xxx_irq_unmask(priv->mc13xxx, MC13XXX_IRQ_RTCRST); out: priv->valid = !ret; mc13xxx_unlock(priv->mc13xxx); return ret; }
int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, unsigned int mode, unsigned int channel, u8 ato, bool atox, unsigned int *sample) { u32 adc0, adc1, old_adc0; int i, ret; struct mc13xxx_adcdone_data adcdone_data = { .mc13xxx = mc13xxx, }; init_completion(&adcdone_data.done); dev_dbg(mc13xxx->dev, "%s\n", __func__); mc13xxx_lock(mc13xxx); if (mc13xxx->adcflags & MC13XXX_ADC_WORKING) { ret = -EBUSY; goto out; } mc13xxx->adcflags |= MC13XXX_ADC_WORKING; mc13xxx_reg_read(mc13xxx, MC13XXX_ADC0, &old_adc0); adc0 = MC13XXX_ADC0_ADINC1 | MC13XXX_ADC0_ADINC2; adc1 = MC13XXX_ADC1_ADEN | MC13XXX_ADC1_ADTRIGIGN | MC13XXX_ADC1_ASC; if (channel > 7) adc1 |= MC13XXX_ADC1_ADSEL; switch (mode) { case MC13XXX_ADC_MODE_TS: adc0 |= MC13XXX_ADC0_ADREFEN | MC13XXX_ADC0_TSMOD0 | MC13XXX_ADC0_TSMOD1; adc1 |= 4 << MC13XXX_ADC1_CHAN1_SHIFT; break; case MC13XXX_ADC_MODE_SINGLE_CHAN: adc0 |= old_adc0 & MC13XXX_ADC0_CONFIG_MASK; adc1 |= (channel & 0x7) << MC13XXX_ADC1_CHAN0_SHIFT; adc1 |= MC13XXX_ADC1_RAND; break; case MC13XXX_ADC_MODE_MULT_CHAN: adc0 |= old_adc0 & MC13XXX_ADC0_CONFIG_MASK; adc1 |= 4 << MC13XXX_ADC1_CHAN1_SHIFT; break; default: mc13xxx_unlock(mc13xxx); return -EINVAL; } adc1 |= ato << MC13783_ADC1_ATO_SHIFT; if (atox) adc1 |= MC13783_ADC1_ATOX; dev_dbg(mc13xxx->dev, "%s: request irq\n", __func__); mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_ADCDONE, mc13xxx_handler_adcdone, __func__, &adcdone_data); mc13xxx_irq_ack(mc13xxx, MC13XXX_IRQ_ADCDONE); mc13xxx_reg_write(mc13xxx, MC13XXX_ADC0, adc0); mc13xxx_reg_write(mc13xxx, MC13XXX_ADC1, adc1); mc13xxx_unlock(mc13xxx); ret = wait_for_completion_interruptible_timeout(&adcdone_data.done, HZ); if (!ret) ret = -ETIMEDOUT; mc13xxx_lock(mc13xxx); mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_ADCDONE, &adcdone_data); if (ret > 0) for (i = 0; i < 4; ++i) { ret = mc13xxx_reg_read(mc13xxx, MC13XXX_ADC2, &sample[i]); if (ret) break; } if (mode == MC13XXX_ADC_MODE_TS) /* restore TSMOD */ mc13xxx_reg_write(mc13xxx, MC13XXX_ADC0, old_adc0); mc13xxx->adcflags &= ~MC13XXX_ADC_WORKING; out: mc13xxx_unlock(mc13xxx); return ret; }
static int mc13xxx_rtc_set_mmss(struct device *dev, time64_t secs) { struct mc13xxx_rtc *priv = dev_get_drvdata(dev); unsigned int seconds, days; unsigned int alarmseconds; int ret; days = div_s64_rem(secs, SEC_PER_DAY, &seconds); mc13xxx_lock(priv->mc13xxx); /* * temporarily invalidate alarm to prevent triggering it when the day is * already updated while the time isn't yet. */ ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTODA, &alarmseconds); if (unlikely(ret)) goto out; if (alarmseconds < SEC_PER_DAY) { ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTODA, 0x1ffff); if (unlikely(ret)) goto out; } /* * write seconds=0 to prevent a day switch between writing days * and seconds below */ ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTOD, 0); if (unlikely(ret)) goto out; ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCDAY, days); if (unlikely(ret)) goto out; ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTOD, seconds); if (unlikely(ret)) goto out; /* restore alarm */ if (alarmseconds < SEC_PER_DAY) { ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTODA, alarmseconds); if (unlikely(ret)) goto out; } if (!priv->valid) { ret = mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_RTCRST); if (unlikely(ret)) goto out; ret = mc13xxx_irq_unmask(priv->mc13xxx, MC13XXX_IRQ_RTCRST); } out: priv->valid = !ret; mc13xxx_unlock(priv->mc13xxx); return ret; }