static inline void enter_state_touch_detect(struct stmp3xxx_ts_info *info) { __raw_writel(0xFFFFFFFF, REGS_LRADC_BASE + HW_LRADC_CHn_CLR(2)); __raw_writel(0xFFFFFFFF, REGS_LRADC_BASE + HW_LRADC_CHn_CLR(3)); __raw_writel(0xFFFFFFFF, REGS_LRADC_BASE + HW_LRADC_CHn_CLR(4)); __raw_writel(0xFFFFFFFF, REGS_LRADC_BASE + HW_LRADC_CHn_CLR(5)); __raw_writel(BM_LRADC_CTRL1_LRADC5_IRQ, REGS_LRADC_BASE + HW_LRADC_CTRL1_CLR); __raw_writel(BM_LRADC_CTRL1_TOUCH_DETECT_IRQ, REGS_LRADC_BASE + HW_LRADC_CTRL1_CLR); /* * turn off the yplus and yminus pullup and pulldown, and turn off touch * detect (enables yminus, and xplus through a resistor.On a press, * xplus is pulled down) */ __raw_writel(BM_LRADC_CTRL0_YMINUS_ENABLE, REGS_LRADC_BASE + HW_LRADC_CTRL0_CLR); __raw_writel(BM_LRADC_CTRL0_YPLUS_ENABLE, REGS_LRADC_BASE + HW_LRADC_CTRL0_CLR); __raw_writel(BM_LRADC_CTRL0_XMINUS_ENABLE, REGS_LRADC_BASE + HW_LRADC_CTRL0_CLR); __raw_writel(BM_LRADC_CTRL0_XPLUS_ENABLE, REGS_LRADC_BASE + HW_LRADC_CTRL0_CLR); __raw_writel(BM_LRADC_CTRL0_TOUCH_DETECT_ENABLE, REGS_LRADC_BASE + HW_LRADC_CTRL0_SET); hw_lradc_set_delay_trigger_kick(LRADC_DELAY_TRIGGER_TOUCHSCREEN, 0); info->state = TS_STATE_TOUCH_DETECT; info->sample_count = 0; }
static void lradc_keypad_hwinit () { /* Clear the Clock Gate and SFTRST for normal operation */ HW_LRADC_CTRL0_CLR(BM_LRADC_CTRL0_SFTRST); HW_LRADC_CTRL0_CLR(BM_LRADC_CTRL0_CLKGATE); /* Disable on-chip ground reference */ HW_LRADC_CTRL0_CLR(BM_LRADC_CTRL0_ONCHIP_GROUNDREF); /* Configure 6Mhz frequency */ HW_LRADC_CTRL3_CLR(BM_LRADC_CTRL3_CYCLE_TIME); HW_LRADC_CTRL3_SET(BF_LRADC_CTRL3_CYCLE_TIME(LRADC_CLOCK_6MHZ)); /* Select VddIO input on channel 6 */ HW_LRADC_CTRL4_CLR(BM_LRADC_CTRL4_LRADC6SELECT); HW_LRADC_CTRL4_SET(BF_LRADC_CTRL4_LRADC6SELECT(lradc_vddio_ch)); /* * Clear the divide by two for channel 6 since it has a HW * divide-by-two built in, and enable this feature for the * button channel */ HW_LRADC_CTRL2_CLR(BF_LRADC_CTRL2_DIVIDE_BY_TWO(1<<VDDIO_VOLTAGE_CH)); HW_LRADC_CTRL2_SET(BF_LRADC_CTRL2_DIVIDE_BY_TWO(1<<lradc_keypad_ch)); /* Clear the accumulator & NUM_SAMPLES */ HW_LRADC_CHn_CLR(VDDIO_VOLTAGE_CH, 0xFFFFFFFF); HW_LRADC_CHn_CLR(lradc_keypad_ch, 0xFFFFFFFF); }
void hw_lradc_configure_channel(int channel, int enable_div2, int enable_acc, int samples) { if (enable_div2) __raw_writel(BF_LRADC_CTRL2_DIVIDE_BY_TWO(1 << channel), mxs_lradc.base + HW_LRADC_CTRL2_SET); else __raw_writel(BF_LRADC_CTRL2_DIVIDE_BY_TWO(1 << channel), mxs_lradc.base + HW_LRADC_CTRL2_CLR); /* Clear the accumulator & NUM_SAMPLES */ __raw_writel(0xFFFFFFFF, mxs_lradc.base + HW_LRADC_CHn_CLR(channel)); /* Sets NUM_SAMPLES bitfield of HW_LRADC_CHn register. */ __raw_writel(BM_LRADC_CHn_NUM_SAMPLES, mxs_lradc.base + HW_LRADC_CHn_CLR(channel)); __raw_writel(BF_LRADC_CHn_NUM_SAMPLES(samples), mxs_lradc.base + HW_LRADC_CHn_SET(channel)); if (enable_acc) __raw_writel(BM_LRADC_CHn_ACCUMULATE, mxs_lradc.base + HW_LRADC_CHn_SET(channel)); else __raw_writel(BM_LRADC_CHn_ACCUMULATE, mxs_lradc.base + HW_LRADC_CHn_CLR(channel)); }
//////////////////////////////////////////////////////////////////////////////// //! See hw_lradc.h for details. //////////////////////////////////////////////////////////////////////////////// void hw_lradc_ConfigureChannel( hw_lradc_Channel_t eChannel, bool bEnableDivideByTwo, bool bEnableAccum, uint8_t u8NumSamples) { // Set the analog divide-by two function if(bEnableDivideByTwo) { // Enable the divide-by-two of a LRADC channel BF_SETV(LRADC_CTRL2, DIVIDE_BY_TWO, (1 << eChannel)); } else { // Disable the divide-by-two of a LRADC channel BF_CLRV(LRADC_CTRL2, DIVIDE_BY_TWO, (1 << eChannel)); } // Clear the accumulator & NUM_SAMPLES HW_LRADC_CHn_CLR(eChannel, 0xFFFFFFFF); // Sets NUM_SAMPLES bitfield of HW_LRADC_CHn register. BF_WRn(LRADC_CHn, eChannel, NUM_SAMPLES, (u8NumSamples & 0x1f)); // Set ACCUMULATE bit of HW_LRADC_CHn register if(bEnableAccum) { // Enable the accumulation of a LRADC channel BF_SETn(LRADC_CHn, eChannel, ACCUMULATE); } else { // Disable the accumulation of a LRADC channel BF_CLRn(LRADC_CHn, eChannel, ACCUMULATE); } }
/* only works for channels <=7, always divide by 2, never accumulates */ static inline void __attribute__((always_inline)) setup_lradc(int src) { BF_CLR(LRADC_CTRL0, SFTRST); BF_CLR(LRADC_CTRL0, CLKGATE); /* don't bother changing the source, we are early enough at boot so that * channel x is mapped to source x */ HW_LRADC_CHn_CLR(src) = BM_OR2(LRADC_CHn, NUM_SAMPLES, ACCUMULATE); BF_SETV(LRADC_CTRL2, DIVIDE_BY_TWO, 1 << src); }
//////////////////////////////////////////////////////////////////////////////// //! See hw_lradc.h for details. //////////////////////////////////////////////////////////////////////////////// RtStatus_t hw_lradc_EnableBatteryMeasurement( hw_lradc_DelayTrigger_t eTrigger, uint16_t u16SamplingInterval) { hw_lradc_Channel_t eChannel = BATTERY_VOLTAGE_CH; // // Check if the lradc channel is present in this product // if( hw_lradc_GetChannelPresent(eChannel) == 0 ) return (ERROR_HW_LRADC_CH_NOT_PRESENT); // Disable the channel interrupt hw_lradc_EnableInterrupt(eChannel, FALSE); hw_lradc_ClearInterruptFlag(eChannel); // Configure the battery conversion register BF_WR(LRADC_CONVERSION, SCALE_FACTOR, 2); // Enable the automatic update mode of BATT_VALUE field in HW_POWER_MONITOR BF_SET(LRADC_CONVERSION, AUTOMATIC); hw_lradc_ConfigureChannel( eChannel, //Lradc channel FALSE, //DIVIDE_BY_TWO FALSE, //ACCUMULATE 0); //NUM_SAMPLES // schedule a conversion before the setting up of the delay channel // so the user can have a good value right after the function returns hw_lradc_ScheduleChannel(eChannel); // Setup the trigger loop forever, hw_lradc_SetDelayTrigger( eTrigger, // Trigger Index (1 << eChannel), // Lradc channels (1 << eTrigger), // Restart the triggers 0, // No loop count u16SamplingInterval); // 0.5*N msec on 2khz // Clear the accumulator & NUM_SAMPLES HW_LRADC_CHn_CLR(eChannel, 0xFFFFFFFF); // Kick off the LRADC battery measurement hw_lradc_SetDelayTriggerKick(eTrigger, TRUE); /* Wait for first measurement of battery. Should occur in 13 LRADC clock * cycles from the time of channel kickoff. Also add some wait time for * copy to the power supply BATT_VAL field to occur. */ hw_digctl_MicrosecondWait(10); return SUCCESS; }
u32 hw_lradc_vddio(void) { /* Clear the Soft Reset and Clock Gate for normal operation */ __raw_writel(BM_LRADC_CTRL0_SFTRST | BM_LRADC_CTRL0_CLKGATE, mxs_lradc.base + HW_LRADC_CTRL0_CLR); /* * Clear the divide by two for channel 6 since * it has a HW divide-by-two built in. */ __raw_writel(BF_LRADC_CTRL2_DIVIDE_BY_TWO(1 << VDDIO_VOLTAGE_CH), mxs_lradc.base + HW_LRADC_CTRL2_CLR); /* Clear the accumulator & NUM_SAMPLES */ __raw_writel(0xFFFFFFFF, mxs_lradc.base + HW_LRADC_CHn_CLR(VDDIO_VOLTAGE_CH)); /* Clear the interrupt flag */ __raw_writel(BM_LRADC_CTRL1_LRADC6_IRQ, mxs_lradc.base + HW_LRADC_CTRL1_CLR); /* * Get VddIO; this is the max scale value for the button resistor * ladder. * schedule ch 6: */ __raw_writel(BF_LRADC_CTRL0_SCHEDULE(1 << VDDIO_VOLTAGE_CH), mxs_lradc.base + HW_LRADC_CTRL0_SET); /* wait for completion */ while ((__raw_readl(mxs_lradc.base + HW_LRADC_CTRL1) & BM_LRADC_CTRL1_LRADC6_IRQ) != BM_LRADC_CTRL1_LRADC6_IRQ) cpu_relax(); /* Clear the interrupt flag */ __raw_writel(BM_LRADC_CTRL1_LRADC6_IRQ, mxs_lradc.base + HW_LRADC_CTRL1_CLR); /* read ch 6 value. */ return __raw_readl(mxs_lradc.base + HW_LRADC_CHn(VDDIO_VOLTAGE_CH)) & BM_LRADC_CHn_VALUE; }
int hw_lradc_init_ladder(int channel, int trigger, unsigned sampling) { /* * check if the lradc channel is present in this product */ if (!hw_lradc_present(channel)) return -ENODEV; hw_lradc_configure_channel(channel, !0 /* div2 */ , 0 /* acc */ , 0 /* num_samples */); /* Setup the trigger loop forever */ hw_lradc_set_delay_trigger(trigger, 1 << channel, 1 << trigger, 0, sampling); /* Clear the accumulator & NUM_SAMPLES */ __raw_writel(0xFFFFFFFF, mxs_lradc.base + HW_LRADC_CHn_CLR(channel)); return 0; }
static int stmp3xxx_ts_probe(struct platform_device *pdev) { struct input_dev *idev; struct stmp3xxx_ts_info *info; int ret = 0; struct resource *res; idev = input_allocate_device(); info = kzalloc(sizeof(struct stmp3xxx_ts_info), GFP_KERNEL); if (idev == NULL || info == NULL) { ret = -ENOMEM; goto out_nomem; } idev->name = "STMP3XXX touchscreen"; idev->evbit[0] = BIT(EV_ABS); input_set_abs_params(idev, ABS_X, 0, 0xFFF, 0, 0); input_set_abs_params(idev, ABS_Y, 0, 0xFFF, 0, 0); input_set_abs_params(idev, ABS_PRESSURE, 0, 1, 0, 0); ret = input_register_device(idev); if (ret) goto out_nomem; info->idev = idev; res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { printk(KERN_ERR "%s: couldn't get IRQ resource\n", __func__); ret = -ENODEV; goto out_nodev; } info->touch_irq = res->start; res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); if (!res) { printk(KERN_ERR "%s: couldn't get IRQ resource\n", __func__); ret = -ENODEV; goto out_nodev; } info->device_irq = res->start; ret = request_irq(info->touch_irq, ts_handler, IRQF_DISABLED, "stmp3xxx_ts_touch", info); if (ret) goto out_nodev; ret = request_irq(info->device_irq, ts_handler, IRQF_DISABLED, "stmp3xxx_ts_dev", info); if (ret) { free_irq(info->touch_irq, info); goto out_nodev; } enter_state_touch_detect(info); hw_lradc_use_channel(LRADC_CH2); hw_lradc_use_channel(LRADC_CH3); hw_lradc_use_channel(LRADC_CH5); hw_lradc_configure_channel(LRADC_CH2, 0, 0, 0); hw_lradc_configure_channel(LRADC_CH3, 0, 0, 0); hw_lradc_configure_channel(LRADC_CH5, 0, 0, 0); /* Clear the accumulator & NUM_SAMPLES for the channels */ __raw_writel(0xFFFFFFFF, REGS_LRADC_BASE + HW_LRADC_CHn_CLR(LRADC_CH2)); __raw_writel(0xFFFFFFFF, REGS_LRADC_BASE + HW_LRADC_CHn_CLR(LRADC_CH3)); __raw_writel(0xFFFFFFFF, REGS_LRADC_BASE + HW_LRADC_CHn_CLR(LRADC_CH5)); hw_lradc_set_delay_trigger(LRADC_DELAY_TRIGGER_TOUCHSCREEN, 0x3c, 0, 0, 8); __raw_writel(BM_LRADC_CTRL1_LRADC5_IRQ, REGS_LRADC_BASE + HW_LRADC_CTRL1_CLR); __raw_writel(BM_LRADC_CTRL1_TOUCH_DETECT_IRQ, REGS_LRADC_BASE + HW_LRADC_CTRL1_CLR); __raw_writel(BM_LRADC_CTRL1_LRADC5_IRQ_EN, REGS_LRADC_BASE + HW_LRADC_CTRL1_SET); __raw_writel(BM_LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, REGS_LRADC_BASE + HW_LRADC_CTRL1_SET); platform_set_drvdata(pdev, info); device_init_wakeup(&pdev->dev, 1); goto out; out_nodev: input_free_device(idev); out_nomem: kfree(idev); kfree(info); out: return ret; }
/* * Use the the lradc1 channel * get the die temperature from on-chip sensor. */ int MeasureInternalDieTemperature(void) { uint32_t ch8Value, ch9Value; /* power up internal tep sensor block */ __raw_writel(BM_LRADC_CTRL2_TEMPSENSE_PWD, REGS_LRADC_BASE + HW_LRADC_CTRL2_CLR); /* mux to the lradc 8th temp channel */ __raw_writel(BF(0xF, LRADC_CTRL4_LRADC1SELECT), REGS_LRADC_BASE + HW_LRADC_CTRL4_CLR); __raw_writel(BF(8, LRADC_CTRL4_LRADC1SELECT), REGS_LRADC_BASE + HW_LRADC_CTRL4_SET); /* Clear the interrupt flag */ __raw_writel(BM_LRADC_CTRL1_LRADC1_IRQ, REGS_LRADC_BASE + HW_LRADC_CTRL1_CLR); __raw_writel(BF(1 << LRADC_CH1, LRADC_CTRL0_SCHEDULE), REGS_LRADC_BASE + HW_LRADC_CTRL0_SET); /* Wait for conversion complete*/ while (!(__raw_readl(REGS_LRADC_BASE + HW_LRADC_CTRL1) & BM_LRADC_CTRL1_LRADC1_IRQ)) cpu_relax(); /* Clear the interrupt flag again */ __raw_writel(BM_LRADC_CTRL1_LRADC1_IRQ, REGS_LRADC_BASE + HW_LRADC_CTRL1_CLR); /* read temperature value and clr lradc */ ch8Value = __raw_readl(REGS_LRADC_BASE + HW_LRADC_CHn(LRADC_CH1)) & BM_LRADC_CHn_VALUE; __raw_writel(BM_LRADC_CHn_VALUE, REGS_LRADC_BASE + HW_LRADC_CHn_CLR(LRADC_CH1)); /* mux to the lradc 9th temp channel */ __raw_writel(BF(0xF, LRADC_CTRL4_LRADC1SELECT), REGS_LRADC_BASE + HW_LRADC_CTRL4_CLR); __raw_writel(BF(9, LRADC_CTRL4_LRADC1SELECT), REGS_LRADC_BASE + HW_LRADC_CTRL4_SET); /* Clear the interrupt flag */ __raw_writel(BM_LRADC_CTRL1_LRADC1_IRQ, REGS_LRADC_BASE + HW_LRADC_CTRL1_CLR); __raw_writel(BF(1 << LRADC_CH1, LRADC_CTRL0_SCHEDULE), REGS_LRADC_BASE + HW_LRADC_CTRL0_SET); /* Wait for conversion complete */ while (!(__raw_readl(REGS_LRADC_BASE + HW_LRADC_CTRL1) & BM_LRADC_CTRL1_LRADC1_IRQ)) cpu_relax(); /* Clear the interrupt flag */ __raw_writel(BM_LRADC_CTRL1_LRADC1_IRQ, REGS_LRADC_BASE + HW_LRADC_CTRL1_CLR); /* read temperature value */ ch9Value = __raw_readl(REGS_LRADC_BASE + HW_LRADC_CHn(LRADC_CH1)) & BM_LRADC_CHn_VALUE; __raw_writel(BM_LRADC_CHn_VALUE, REGS_LRADC_BASE + HW_LRADC_CHn_CLR(LRADC_CH1)); /* power down temp sensor block */ __raw_writel(BM_LRADC_CTRL2_TEMPSENSE_PWD, REGS_LRADC_BASE + HW_LRADC_CTRL2_SET); return ((ch9Value-ch8Value)*GAIN_CORRECTION/4 - KELVIN_TO_CELSIUS_CONST); }