/* * Freescale STMP37XX/STMP378X LRADC helper routines * * Embedded Alley Solutions, Inc * * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. */ /* * The code contained herein is licensed under the GNU General Public * License. You may obtain a copy of the GNU General Public License * Version 2 or later at the following locations: * * http://www.opensource.org/licenses/gpl-license.html * http://www.gnu.org/copyleft/gpl.html */ #include #include #include #include #include #include #include #include #include #include static int channels[8]; int hw_lradc_use_channel(int channel) { if (channel < 0 || channel > 7) return -EINVAL; channels[channel]++; return 0; } EXPORT_SYMBOL(hw_lradc_use_channel); int hw_lradc_unuse_channel(int channel) { if (channel < 0 || channel > 7) return -EINVAL; channels[channel]--; return 0; } EXPORT_SYMBOL(hw_lradc_unuse_channel); void hw_lradc_reinit(int enable_ground_ref, unsigned freq) { HW_LRADC_CTRL0_SET(BM_LRADC_CTRL0_SFTRST); udelay(1); HW_LRADC_CTRL0_CLR(BM_LRADC_CTRL0_SFTRST); /* Clear the Clock Gate for normal operation */ HW_LRADC_CTRL0_CLR(BM_LRADC_CTRL0_CLKGATE); if (enable_ground_ref) HW_LRADC_CTRL0_SET(BM_LRADC_CTRL0_ONCHIP_GROUNDREF); else HW_LRADC_CTRL0_CLR(BM_LRADC_CTRL0_ONCHIP_GROUNDREF); HW_LRADC_CTRL3_CLR(BM_LRADC_CTRL3_CYCLE_TIME); HW_LRADC_CTRL3_SET(BF_LRADC_CTRL3_CYCLE_TIME(freq)); HW_LRADC_CTRL4_CLR(BM_LRADC_CTRL4_LRADC6SELECT | BM_LRADC_CTRL4_LRADC7SELECT); HW_LRADC_CTRL4_SET(BF_LRADC_CTRL4_LRADC6SELECT(VDDIO_VOLTAGE_CH)); HW_LRADC_CTRL4_SET(BF_LRADC_CTRL4_LRADC7SELECT(BATTERY_VOLTAGE_CH)); } 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< 7) return 0; return HW_LRADC_STATUS_RD() & (1<<(16+channel)); } EXPORT_SYMBOL(hw_lradc_present); void hw_lradc_configure_channel(int channel, int enable_div2, int enable_acc, int samples) { if (enable_div2) HW_LRADC_CTRL2_SET(BF_LRADC_CTRL2_DIVIDE_BY_TWO(1< 0) { do_gate = 0; break; } for (i = 0; i < ARRAY_SIZE(lradc_registers); i++) lradc_registers[i] = __raw_readl(REGS_LRADC_BASE + (i << 4)); if (do_gate) HW_LRADC_CTRL0_SET(BM_LRADC_CTRL0_CLKGATE); return 0; } static int hw_lradc_resume(struct sys_device *dev) { int i; if (do_gate) { HW_LRADC_CTRL0_SET(BM_LRADC_CTRL0_SFTRST); udelay(10); HW_LRADC_CTRL0_CLR(BM_LRADC_CTRL0_SFTRST | BM_LRADC_CTRL0_CLKGATE); } for (i = 0; i < ARRAY_SIZE(lradc_registers); i++) __raw_writel(lradc_registers[i], REGS_LRADC_BASE + (i << 4)); return 0; } static struct sysdev_class stmp3xxx_lradc_sysclass = { .name = "stmp3xxx-lradc", #ifdef CONFIG_PM .suspend = hw_lradc_suspend, .resume = hw_lradc_resume, #endif }; static struct sys_device stmp3xxx_lradc_device = { .id = -1, .cls = &stmp3xxx_lradc_sysclass, }; static int __initdata lradc_freq = LRADC_CLOCK_6MHZ; static int __init lradc_freq_setup(char *str) { long freq; if (strict_strtol(str, 0, &freq) < 0) return 0; if (freq < 0) return 0; if (freq >= 6) lradc_freq = LRADC_CLOCK_6MHZ; else if (freq >= 4) lradc_freq = LRADC_CLOCK_4MHZ; else if (freq >= 3) lradc_freq = LRADC_CLOCK_3MHZ; else if (freq >= 2) lradc_freq = LRADC_CLOCK_2MHZ; else return 0; return 1; } __setup("lradc_freq=", lradc_freq_setup); static int __init hw_lradc_init(void) { hw_lradc_reinit(0, lradc_freq); sysdev_class_register(&stmp3xxx_lradc_sysclass); sysdev_register(&stmp3xxx_lradc_device); return 0; } subsys_initcall(hw_lradc_init);