| /* |
| * arch/arm/plat-ambarella/generic/adc.c |
| * |
| * Author: Anthony Ginger <hfjiang@ambarella.com> |
| * |
| * Copyright (C) 2004-2009, Ambarella, Inc. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| * |
| */ |
| |
| #include <linux/kernel.h> |
| #include <linux/init.h> |
| #include <linux/platform_device.h> |
| #include <linux/bootmem.h> |
| #include <linux/delay.h> |
| #include <linux/irq.h> |
| #include <linux/dma-mapping.h> |
| #include <linux/moduleparam.h> |
| #include <linux/proc_fs.h> |
| #include <asm/uaccess.h> |
| |
| #include <mach/hardware.h> |
| #include <plat/adc.h> |
| |
| /* ==========================================================================*/ |
| #ifdef MODULE_PARAM_PREFIX |
| #undef MODULE_PARAM_PREFIX |
| #endif |
| #define MODULE_PARAM_PREFIX "ambarella_config." |
| |
| static atomic_t use_count; |
| |
| static DEFINE_MUTEX(adc_lock); |
| /* ==========================================================================*/ |
| #if ((CHIP_REV == A5) || (CHIP_REV == A6) || (CHIP_REV == A5S) ||\ |
| (CHIP_REV == A7) || (CHIP_REV == A5L)) |
| #undef ADC_ONE_SHOT |
| #define ADC_ONE_SHOT |
| #else |
| #define ADC_ONE_SHOT |
| #endif /* CHIP_REV */ |
| |
| #ifndef CONFIG_AMBARELLA_ADC_WAIT_COUNTER_LIMIT |
| #define CONFIG_AMBARELLA_ADC_WAIT_COUNTER_LIMIT (100000) |
| #endif |
| |
| /* ==========================================================================*/ |
| u32 ambarella_adc_get_instances(void) |
| { |
| return ADC_NUM_CHANNELS; |
| } |
| |
| u32 ambarella_adc_get_channel_inline(u32 channel_id) |
| { |
| u32 adc_data = 0; |
| |
| mutex_lock(&adc_lock); |
| |
| #if defined(ADC_ONE_SHOT) |
| amba_setbitsl(ADC_CONTROL_REG, ADC_CONTROL_START); |
| #if ((CHIP_REV == A5) || (CHIP_REV == A6) || (CHIP_REV == A5S) || \ |
| (CHIP_REV == A7) || (CHIP_REV == A5L)) |
| while (amba_tstbitsl(ADC_CONTROL_REG, ADC_CONTROL_STATUS) == 0x0) { |
| msleep(1); |
| } |
| #else |
| while (amba_tstbitsl(ADC_CONTROL_REG, ADC_CONTROL_STATUS) == 0x0); |
| #endif |
| #endif |
| |
| switch(channel_id) { |
| #if (ADC_NUM_CHANNELS == 8) |
| case 0: |
| adc_data = (amba_readl(ADC_DATA0_REG) + 0x8000) & 0xffff; |
| break; |
| case 1: |
| adc_data = (amba_readl(ADC_DATA1_REG) + 0x8000) & 0xffff; |
| break; |
| case 2: |
| adc_data = (amba_readl(ADC_DATA2_REG) + 0x8000) & 0xffff; |
| break; |
| case 3: |
| adc_data = (amba_readl(ADC_DATA3_REG) + 0x8000) & 0xffff; |
| break; |
| case 4: |
| adc_data = (amba_readl(ADC_DATA4_REG) + 0x8000) & 0xffff; |
| break; |
| case 5: |
| adc_data = (amba_readl(ADC_DATA5_REG) + 0x8000) & 0xffff; |
| break; |
| case 6: |
| adc_data = (amba_readl(ADC_DATA6_REG) + 0x8000) & 0xffff; |
| break; |
| case 7: |
| adc_data = (amba_readl(ADC_DATA7_REG) + 0x8000) & 0xffff; |
| break; |
| #else |
| case 0: |
| adc_data = amba_readl(ADC_DATA0_REG); |
| break; |
| case 1: |
| adc_data = amba_readl(ADC_DATA1_REG); |
| break; |
| case 2: |
| adc_data = amba_readl(ADC_DATA2_REG); |
| break; |
| case 3: |
| adc_data = amba_readl(ADC_DATA3_REG); |
| break; |
| #if (ADC_NUM_CHANNELS >= 6) |
| case 4: |
| adc_data = amba_readl(ADC_DATA4_REG); |
| break; |
| case 5: |
| adc_data = amba_readl(ADC_DATA5_REG); |
| break; |
| #endif |
| #if (ADC_NUM_CHANNELS >= 10) |
| case 6: |
| adc_data = amba_readl(ADC_DATA6_REG); |
| break; |
| case 7: |
| adc_data = amba_readl(ADC_DATA7_REG); |
| break; |
| case 8: |
| adc_data = amba_readl(ADC_DATA8_REG); |
| break; |
| case 9: |
| adc_data = amba_readl(ADC_DATA9_REG); |
| break; |
| #endif |
| #endif |
| default: |
| pr_warning("%s: invalid adc channel id %d!\n", |
| __func__, channel_id); |
| break; |
| } |
| pr_debug("%s: channel[%d] = %d.\n", __func__, channel_id, adc_data); |
| |
| mutex_unlock(&adc_lock); |
| |
| return adc_data; |
| } |
| |
| void ambarella_adc_get_array(u32 *adc_data, u32 *array_size) |
| { |
| int i; |
| |
| if (unlikely(*array_size > ADC_NUM_CHANNELS)) { |
| pr_err("%s: array_size should be %d, not %d!\n", |
| __func__, ADC_NUM_CHANNELS, *array_size); |
| return; |
| } |
| |
| if (!readl(ADC_ENABLE_REG)) { |
| pr_err("%s: tried to read ADC while it is not on\n", __func__); |
| return; |
| } |
| |
| mutex_lock(&adc_lock); |
| |
| #if defined(ADC_ONE_SHOT) |
| amba_setbitsl(ADC_CONTROL_REG, ADC_CONTROL_START); |
| #if ((CHIP_REV == A5) || (CHIP_REV == A6) || (CHIP_REV == A5S) || \ |
| (CHIP_REV == A7) || (CHIP_REV == A5L)) |
| while (amba_tstbitsl(ADC_CONTROL_REG, ADC_CONTROL_STATUS) == 0x0) { |
| msleep(1); |
| } |
| #else |
| while (amba_tstbitsl(ADC_CONTROL_REG, ADC_CONTROL_STATUS) == 0x0); |
| #endif |
| #endif |
| |
| #if (ADC_NUM_CHANNELS == 8) |
| adc_data[0] = (amba_readl(ADC_DATA0_REG) + 0x8000) & 0xffff; |
| adc_data[1] = (amba_readl(ADC_DATA1_REG) + 0x8000) & 0xffff; |
| adc_data[2] = (amba_readl(ADC_DATA2_REG) + 0x8000) & 0xffff; |
| adc_data[3] = (amba_readl(ADC_DATA3_REG) + 0x8000) & 0xffff; |
| adc_data[4] = (amba_readl(ADC_DATA4_REG) + 0x8000) & 0xffff; |
| adc_data[5] = (amba_readl(ADC_DATA5_REG) + 0x8000) & 0xffff; |
| adc_data[6] = (amba_readl(ADC_DATA6_REG) + 0x8000) & 0xffff; |
| adc_data[7] = (amba_readl(ADC_DATA7_REG) + 0x8000) & 0xffff; |
| #else |
| adc_data[0] = amba_readl(ADC_DATA0_REG); |
| adc_data[1] = amba_readl(ADC_DATA1_REG); |
| adc_data[2] = amba_readl(ADC_DATA2_REG); |
| adc_data[3] = amba_readl(ADC_DATA3_REG); |
| #if (ADC_NUM_CHANNELS >= 6) |
| adc_data[4] = amba_readl(ADC_DATA4_REG); |
| adc_data[5] = amba_readl(ADC_DATA5_REG); |
| #endif |
| #if (ADC_NUM_CHANNELS >= 10) |
| adc_data[6] = amba_readl(ADC_DATA6_REG); |
| adc_data[7] = amba_readl(ADC_DATA7_REG); |
| adc_data[8] = amba_readl(ADC_DATA8_REG); |
| adc_data[9] = amba_readl(ADC_DATA9_REG); |
| #endif |
| #endif |
| |
| mutex_unlock(&adc_lock); |
| |
| for (i = 0; i < ADC_NUM_CHANNELS; i++) |
| pr_debug("%s: channel[%d] = %d.\n", __func__, i, adc_data[i]); |
| } |
| |
| EXPORT_SYMBOL(ambarella_adc_get_array); |
| |
| void ambarella_adc_start(void) |
| { |
| mutex_lock(&adc_lock); |
| |
| #if defined(ADC16_CTRL_REG) |
| amba_clrbitsl(ADC16_CTRL_REG, 0x2); |
| #endif |
| |
| #if (CHIP_REV == A5L) |
| amba_writel(ADC_CONTROL_REG, 0x0); |
| |
| amba_writel(ADC_DATA0_REG, 0); |
| amba_writel(ADC_DATA1_REG, 0); |
| amba_writel(ADC_DATA2_REG, 0); |
| amba_writel(ADC_DATA3_REG, 0); |
| |
| amba_writel(ADC_ENABLE_REG, 0x0); |
| #endif |
| |
| #if (CHIP_REV == A5 || CHIP_REV == A6) |
| /* SCALER_ADC_REG (default=4) */ |
| /* clk_au = 27MHz/2 */ |
| rct_set_adc_clk_freq_hz(PLL_CLK_13_5MHZ); |
| |
| /* ADC Analog (lowest power) */ |
| amba_writel(ADC16_CTRL_REG, 0x031cff); |
| |
| /* ADC reset */ |
| amba_writel(ADC_RESET_REG, 0x1); |
| |
| /* Fix nonlinearity */ |
| amba_writel(ADC16_CTRL_REG, 0x00031c00); |
| #endif |
| |
| #if (CHIP_REV == A5S) |
| /* stop conversion */ |
| amba_writel(ADC_CONTROL_REG, 0x0); |
| |
| amba_writel(ADC_DATA0_REG, 0); |
| amba_writel(ADC_DATA1_REG, 0); |
| amba_writel(ADC_DATA2_REG, 0); |
| amba_writel(ADC_DATA3_REG, 0); |
| |
| amba_writel(ADC_ENABLE_REG, 0x0); |
| #endif |
| |
| #if (CHIP_REV == A7) |
| /* stop conversion */ |
| amba_writel(ADC_CONTROL_REG, 0x0); |
| |
| amba_writel(ADC_DATA0_REG, 0); |
| amba_writel(ADC_DATA1_REG, 0); |
| amba_writel(ADC_DATA2_REG, 0); |
| amba_writel(ADC_DATA3_REG, 0); |
| |
| amba_writel(ADC_ENABLE_REG, 0x1); |
| amba_writel(ADC_CONTROL_REG, 0x1); |
| #else |
| #if (CHIP_REV != I1) |
| if (amba_readl(ADC_ENABLE_REG) != 0) { |
| pr_err("%s: ADC_ENABLE_REG = %d.\n", |
| __func__, amba_readl(ADC_ENABLE_REG)); |
| mutex_unlock(&adc_lock); |
| return; |
| } |
| #endif |
| amba_writel(ADC_ENABLE_REG, 0x1); |
| #endif |
| |
| #ifdef ADC_ONE_SHOT |
| /* ADC control mode, single */ |
| amba_clrbitsl(ADC_CONTROL_REG, ADC_CONTROL_MODE); |
| #else |
| /* ADC control mode, continuous */ |
| amba_setbitsl(ADC_CONTROL_REG, ADC_CONTROL_MODE); |
| |
| /* start conversion */ |
| amba_setbitsl(ADC_CONTROL_REG, ADC_CONTROL_START); |
| while (amba_tstbitsl(ADC_CONTROL_REG, ADC_CONTROL_STATUS) == 0x0); |
| #endif |
| |
| mutex_unlock(&adc_lock); |
| } |
| |
| void ambarella_adc_stop(void) |
| { |
| mutex_lock(&adc_lock); |
| #ifndef ADC_ONE_SHOT |
| amba_writel(ADC_CONTROL_REG, 0x0); |
| #endif |
| amba_writel(ADC_ENABLE_REG, 0x0); |
| #if (CHIP_REV == A7) |
| amba_writel(ADC_CONTROL_REG, 0x0); |
| #endif |
| #if defined(ADC16_CTRL_REG) |
| amba_setbitsl(ADC16_CTRL_REG, 0x2); |
| #endif |
| mutex_unlock(&adc_lock); |
| } |
| |
| #ifdef CONFIG_AMBARELLA_ADC_PROC |
| #define AMBARELLA_ADC_PROC_READ_SIZE (13) |
| static const char adc_proc_name[] = "adc"; |
| static struct proc_dir_entry *adc_file; |
| |
| static int ambarella_adc_proc_write(struct file *file, |
| const char __user *buffer, unsigned long count, void *data) |
| { |
| int read_counter = 0; |
| char cmd; |
| |
| if (copy_from_user(&cmd, buffer, 1)) { |
| pr_err("%s: copy_from_user fail!\n", __func__); |
| read_counter = -EFAULT; |
| goto ambarella_adc_proc_write_exit; |
| } |
| read_counter = count; |
| |
| if (cmd == '1') { |
| ambarella_adc_start(); |
| } else { |
| ambarella_adc_stop(); |
| } |
| |
| ambarella_adc_proc_write_exit: |
| return read_counter; |
| } |
| |
| static int ambarella_adc_proc_read(char *page, char **start, |
| off_t off, int count, int *eof, void *data) |
| { |
| int len = 0; |
| int i; |
| u32 adc_data[ADC_NUM_CHANNELS]; |
| int adc_size; |
| |
| adc_size = ambarella_adc_get_instances(); |
| |
| if (off > (adc_size * AMBARELLA_ADC_PROC_READ_SIZE)) { |
| *eof = 1; |
| return 0; |
| } |
| |
| *start = page + off; |
| |
| if (count > (adc_size * AMBARELLA_ADC_PROC_READ_SIZE)) { |
| count = (adc_size * AMBARELLA_ADC_PROC_READ_SIZE); |
| *eof = 1; |
| } |
| |
| if ((off + count) > (adc_size * AMBARELLA_ADC_PROC_READ_SIZE)) { |
| count = (adc_size * AMBARELLA_ADC_PROC_READ_SIZE) - off; |
| *eof = 1; |
| } |
| |
| adc_size = count / AMBARELLA_ADC_PROC_READ_SIZE; |
| ambarella_adc_get_array(adc_data, &adc_size); |
| for (i = off / AMBARELLA_ADC_PROC_READ_SIZE; i < adc_size; i++) |
| len += sprintf(*start + len, "adc%d = 0x%03x\n", |
| i, adc_data[i]); |
| |
| return len; |
| } |
| #endif |
| |
| int __init ambarella_init_adc(void) |
| { |
| int retval = 0; |
| |
| atomic_set(&use_count, -1); |
| |
| #ifdef CONFIG_AMBARELLA_ADC_PROC |
| adc_file = create_proc_entry(adc_proc_name, S_IRUGO | S_IWUSR, |
| get_ambarella_proc_dir()); |
| if (adc_file == NULL) { |
| retval = -ENOMEM; |
| pr_err("%s: %s fail!\n", __func__, adc_proc_name); |
| } else { |
| adc_file->read_proc = ambarella_adc_proc_read; |
| adc_file->write_proc = ambarella_adc_proc_write; |
| } |
| #endif |
| |
| return retval; |
| } |
| |
| u32 adc_is_irq_supported(void) |
| { |
| #if (ADC_SUPPORT_THRESHOLD_INT == 1) |
| #ifndef ADC_ONE_SHOT |
| return 1; |
| #else |
| return 0; |
| #endif |
| #else |
| return 0; |
| #endif |
| } |
| |
| void adc_set_irq_threshold(u32 ch, u32 h_level, u32 l_level) |
| { |
| #if (ADC_SUPPORT_THRESHOLD_INT == 1) |
| u32 irq_control_address = 0; |
| u32 value = ADC_EN_HI(!!h_level) | ADC_EN_LO(!!l_level) | |
| ADC_VAL_HI(h_level) | ADC_VAL_LO(l_level); |
| |
| switch (ch) { |
| case 0: |
| irq_control_address = ADC_CHAN0_INTR_REG; |
| break; |
| case 1: |
| irq_control_address = ADC_CHAN1_INTR_REG; |
| break; |
| case 2: |
| irq_control_address = ADC_CHAN2_INTR_REG; |
| break; |
| case 3: |
| irq_control_address = ADC_CHAN3_INTR_REG; |
| break; |
| #if (ADC_NUM_CHANNELS >= 6) |
| case 4: |
| irq_control_address = ADC_CHAN4_INTR_REG; |
| break; |
| case 5: |
| irq_control_address = ADC_CHAN5_INTR_REG; |
| break; |
| #endif |
| #if (ADC_NUM_CHANNELS >= 8) |
| case 6: |
| irq_control_address = ADC_CHAN6_INTR_REG; |
| break; |
| case 7: |
| irq_control_address = ADC_CHAN7_INTR_REG; |
| break; |
| #endif |
| #if (ADC_NUM_CHANNELS >= 10) |
| case 8: |
| irq_control_address = ADC_CHAN8_INTR_REG; |
| break; |
| case 9: |
| irq_control_address = ADC_CHAN9_INTR_REG; |
| break; |
| #endif |
| default: |
| printk("Don't support %d channels\n", ch); |
| return; |
| } |
| amba_writel(irq_control_address, value); |
| pr_err("%s: set ch[%d] h[%d], l[%d], 0x%08X!\n", |
| __func__, ch, h_level, l_level, value); |
| #endif |
| } |
| |
| u32 amb_temper_curve(u32 adc_data) |
| { |
| return ((((1083 * adc_data * 315) / 4096) - 81900) / 1000);// Tj=(108.3 * adc_value * 3.15 / 4096) - 81.9 |
| } |
| |
| u32 ambarella_adc_open(void) |
| { |
| if(atomic_inc_and_test(&use_count)) |
| ambarella_adc_start(); |
| return 0; |
| } |
| |
| u32 ambarella_adc_close(void) |
| { |
| if(atomic_read(&use_count) < 0) |
| return -1; |
| |
| if(atomic_dec_return(&use_count) == (-1)){ |
| ambarella_adc_stop(); |
| } |
| return 0; |
| } |
| |
| /* ==========================================================================*/ |
| struct ambarella_adc_pm_info { |
| #if defined(ADC16_CTRL_REG) |
| u32 adc_rct_reg; |
| #endif |
| u32 adc_control_reg; |
| u32 adc_enable_reg; |
| u32 adc_chan0_intr_reg; |
| u32 adc_chan1_intr_reg; |
| u32 adc_chan2_intr_reg; |
| u32 adc_chan3_intr_reg; |
| #if (ADC_NUM_CHANNELS >= 6) |
| u32 adc_chan4_intr_reg; |
| u32 adc_chan5_intr_reg; |
| #endif |
| #if (ADC_NUM_CHANNELS >= 8) |
| u32 adc_chan6_intr_reg; |
| u32 adc_chan7_intr_reg; |
| #endif |
| #if (ADC_NUM_CHANNELS >= 10) |
| u32 adc_chan8_intr_reg; |
| u32 adc_chan9_intr_reg; |
| #endif |
| }; |
| |
| struct ambarella_adc_pm_info ambarella_adc_pm; |
| |
| u32 ambarella_adc_suspend(u32 level) |
| { |
| #if defined(ADC16_CTRL_REG) |
| ambarella_adc_pm.adc_rct_reg = amba_readl(ADC16_CTRL_REG); |
| #endif |
| ambarella_adc_pm.adc_control_reg = amba_readl(ADC_CONTROL_REG); |
| ambarella_adc_pm.adc_enable_reg = amba_readl(ADC_ENABLE_REG); |
| ambarella_adc_pm.adc_chan0_intr_reg = amba_readl(ADC_CHAN0_INTR_REG); |
| ambarella_adc_pm.adc_chan1_intr_reg = amba_readl(ADC_CHAN1_INTR_REG); |
| ambarella_adc_pm.adc_chan2_intr_reg = amba_readl(ADC_CHAN2_INTR_REG); |
| ambarella_adc_pm.adc_chan3_intr_reg = amba_readl(ADC_CHAN3_INTR_REG); |
| #if (ADC_NUM_CHANNELS >= 6) |
| ambarella_adc_pm.adc_chan4_intr_reg = amba_readl(ADC_CHAN4_INTR_REG); |
| ambarella_adc_pm.adc_chan5_intr_reg = amba_readl(ADC_CHAN5_INTR_REG); |
| #endif |
| #if (ADC_NUM_CHANNELS >= 8) |
| ambarella_adc_pm.adc_chan6_intr_reg = amba_readl(ADC_CHAN6_INTR_REG); |
| ambarella_adc_pm.adc_chan7_intr_reg = amba_readl(ADC_CHAN7_INTR_REG); |
| #endif |
| #if (ADC_NUM_CHANNELS >= 10) |
| ambarella_adc_pm.adc_chan8_intr_reg = amba_readl(ADC_CHAN8_INTR_REG); |
| ambarella_adc_pm.adc_chan9_intr_reg = amba_readl(ADC_CHAN9_INTR_REG); |
| #endif |
| |
| return 0; |
| } |
| |
| u32 ambarella_adc_resume(u32 level) |
| { |
| #if defined(ADC16_CTRL_REG) |
| amba_writel(ADC16_CTRL_REG, ambarella_adc_pm.adc_rct_reg); |
| #endif |
| if (ambarella_adc_pm.adc_enable_reg & 0x01) { |
| amba_writel(ADC_ENABLE_REG, ambarella_adc_pm.adc_enable_reg); |
| |
| if ((amba_readl(ADC_CONTROL_REG) & 0xfffffffc) != 0) { |
| amba_writel(ADC_CONTROL_REG, 0x0); |
| while ((amba_readl(ADC_CONTROL_REG) & ADC_CONTROL_STATUS) == 0x0); |
| } |
| if ((ambarella_adc_pm.adc_control_reg & 0xfffffffe) != 0) { |
| amba_writel(ADC_CONTROL_REG, ambarella_adc_pm.adc_control_reg & 0xfffffffe); |
| while ((amba_readl(ADC_CONTROL_REG) & ADC_CONTROL_STATUS) == 0x0); |
| } |
| |
| amba_writel(ADC_CHAN0_INTR_REG, ambarella_adc_pm.adc_chan0_intr_reg); |
| amba_writel(ADC_CHAN1_INTR_REG, ambarella_adc_pm.adc_chan1_intr_reg); |
| amba_writel(ADC_CHAN2_INTR_REG, ambarella_adc_pm.adc_chan2_intr_reg); |
| amba_writel(ADC_CHAN3_INTR_REG, ambarella_adc_pm.adc_chan3_intr_reg); |
| #if (ADC_NUM_CHANNELS >= 6) |
| amba_writel(ADC_CHAN4_INTR_REG, ambarella_adc_pm.adc_chan4_intr_reg); |
| amba_writel(ADC_CHAN5_INTR_REG, ambarella_adc_pm.adc_chan5_intr_reg); |
| #endif |
| #if (ADC_NUM_CHANNELS >= 8) |
| amba_writel(ADC_CHAN6_INTR_REG, ambarella_adc_pm.adc_chan6_intr_reg); |
| amba_writel(ADC_CHAN7_INTR_REG, ambarella_adc_pm.adc_chan7_intr_reg); |
| #endif |
| #if (ADC_NUM_CHANNELS >= 10) |
| amba_writel(ADC_CHAN8_INTR_REG, ambarella_adc_pm.adc_chan8_intr_reg); |
| amba_writel(ADC_CHAN9_INTR_REG, ambarella_adc_pm.adc_chan9_intr_reg); |
| #endif |
| } |
| |
| return 0; |
| } |
| |
| /* ==========================================================================*/ |
| struct ambarella_adc_controller ambarella_platform_adc_controller0 = { |
| .open = ambarella_adc_open, |
| .close = ambarella_adc_close, |
| .read_channels = ambarella_adc_get_array, |
| .is_irq_supported = adc_is_irq_supported, |
| .set_irq_threshold = adc_set_irq_threshold, |
| .reset = ambarella_adc_start, |
| .stop = ambarella_adc_stop, |
| .get_channel_num = ambarella_adc_get_instances, |
| |
| .scan_delay = 20, |
| }; |
| AMBA_ADC_PARAM_CALL(ambarella_platform_adc_controller0, 0644); |
| |
| struct resource ambarella_adc_resources[] = { |
| [0] = { |
| .start = ADC_BASE, |
| .end = ADC_BASE + 0x0FFF, |
| .name = "registers", |
| .flags = IORESOURCE_MEM, |
| }, |
| #if (CHIP_REV == A5S || CHIP_REV == A7) |
| [1] = { |
| .start = ADC_LEVEL_IRQ, |
| .end = ADC_LEVEL_IRQ, |
| .name = "adc-level-irq", |
| .flags = IORESOURCE_IRQ, |
| }, |
| #endif |
| }; |
| |
| struct platform_device ambarella_adc0 = { |
| .name = "ambarella-adc", |
| .id = -1, |
| .resource = ambarella_adc_resources, |
| .num_resources = ARRAY_SIZE(ambarella_adc_resources), |
| .dev = { |
| .platform_data = &ambarella_platform_adc_controller0, |
| .dma_mask = &ambarella_dmamask, |
| .coherent_dma_mask = DMA_BIT_MASK(32), |
| } |
| }; |
| |
| struct ambarella_adc_controller ambarella_platform_adc_temper_controller0 = { |
| .open = ambarella_adc_open, |
| .close = ambarella_adc_close, |
| .read_channel = ambarella_adc_get_channel_inline, |
| .reset = ambarella_adc_start, |
| .stop = ambarella_adc_stop, |
| .get_channel_num = ambarella_adc_get_instances, |
| .temper_curve = NULL, |
| .adc_temper_channel = -1, |
| }; |
| |
| struct platform_device ambarella_adc_temper = { |
| .name = "ambarella-adc-temper", |
| .id = -1, |
| .dev = { |
| .platform_data = &ambarella_platform_adc_temper_controller0, |
| .dma_mask = &ambarella_dmamask, |
| .coherent_dma_mask = DMA_BIT_MASK(32), |
| } |
| }; |
| |
| |
| |