blob: ab9d8c29906272b8f0b641da8014c132161f5f6d [file] [log] [blame]
/*
* arch/arm/plat-ambarella/include/plat/adc.h
*
* Author: Anthony Ginger <hfjiang@ambarella.com>
*
* Copyright (C) 2004-2010, 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
*
*/
#ifndef __PLAT_AMBARELLA_ADC_H__
#define __PLAT_AMBARELLA_ADC_H__
#include <linux/workqueue.h>
/* ==========================================================================*/
#if (CHIP_REV == A7L)
#define ADC_NUM_CHANNELS 8
#elif (CHIP_REV == S2) || (CHIP_REV == S2E)
#define ADC_NUM_CHANNELS 12
#elif (CHIP_REV == S3)
#define ADC_NUM_CHANNELS 5
#else
#define ADC_NUM_CHANNELS 4
#endif
#if (CHIP_REV == A5S)
#define ADC_SUPPORT_THRESHOLD_INT 0
#define ADC_SUPPORT_SLOT 0
#else
#define ADC_SUPPORT_THRESHOLD_INT 1
#define ADC_SUPPORT_SLOT 1
#endif
/* ==========================================================================*/
#if (CHIP_REV == S2L) || (CHIP_REV == S3) || (CHIP_REV == S3L)
#define ADC_OFFSET 0x1D000
#else
#define ADC_OFFSET 0xD000
#endif
#define ADC_BASE (APB_BASE + ADC_OFFSET)
#define ADC_REG(x) (ADC_BASE + (x))
/* ==========================================================================*/
#if (CHIP_REV == A5S)
#define ADC_CONTROL_TYPE 0
#define ADC_CONTROL_OFFSET 0x00
#define ADC_ENABLE_OFFSET 0x18
#else
#define ADC_CONTROL_TYPE 1
#define ADC_CONTROL_OFFSET 0x04
#define ADC_ENABLE_OFFSET ADC_CONTROL_OFFSET
#endif
#if (CHIP_REV == A5S)
/* NOTE: ADC channel is re-order for A5S to make life easier */
#define ADC_DATA0_OFFSET 0x04
#define ADC_DATA1_OFFSET 0x08
#define ADC_DATA2_OFFSET 0x0c
#define ADC_DATA3_OFFSET 0x10
#else
#define ADC_DATA0_OFFSET 0x150
#define ADC_DATA1_OFFSET 0x154
#define ADC_DATA2_OFFSET 0x158
#define ADC_DATA3_OFFSET 0x15c
#endif
#define ADC_COUNTER_OFFSET 0x008
#if (CHIP_REV == A5S)
#define ADC_CHAN0_INTR_OFFSET 0x44
#define ADC_CHAN1_INTR_OFFSET 0x48
#define ADC_CHAN2_INTR_OFFSET 0x4c
#define ADC_CHAN3_INTR_OFFSET 0x50
#else
#define ADC_CHAN0_INTR_OFFSET 0x120
#define ADC_CHAN1_INTR_OFFSET 0x124
#define ADC_CHAN2_INTR_OFFSET 0x128
#define ADC_CHAN3_INTR_OFFSET 0x12c
#endif
#if (CHIP_REV == A7L)
#define ADC_DATA4_OFFSET 0x100
#define ADC_DATA5_OFFSET 0x104
#define ADC_DATA6_OFFSET 0x108
#define ADC_DATA7_OFFSET 0x10c
#define ADC_CHAN4_INTR_OFFSET 0x110
#define ADC_CHAN5_INTR_OFFSET 0x114
#define ADC_CHAN6_INTR_OFFSET 0x118
#define ADC_CHAN7_INTR_OFFSET 0x11c
#elif (CHIP_REV == S2) || (CHIP_REV == S2E) || (CHIP_REV == S3)
#define ADC_DATA4_OFFSET 0x160
#define ADC_DATA5_OFFSET 0x164
#define ADC_DATA6_OFFSET 0x168
#define ADC_DATA7_OFFSET 0x16c
#define ADC_CHAN4_INTR_OFFSET 0x130
#define ADC_CHAN5_INTR_OFFSET 0x134
#define ADC_CHAN6_INTR_OFFSET 0x138
#define ADC_CHAN7_INTR_OFFSET 0x13c
#else
#define ADC_DATA4_OFFSET 0x54
#define ADC_DATA5_OFFSET 0x58
#define ADC_DATA6_OFFSET 0x5c
#define ADC_DATA7_OFFSET 0x60
#define ADC_CHAN4_INTR_OFFSET 0x64
#define ADC_CHAN5_INTR_OFFSET 0x68
#define ADC_CHAN6_INTR_OFFSET 0x6c
#define ADC_CHAN7_INTR_OFFSET 0x70
#endif
#if (CHIP_REV == S2) || (CHIP_REV == S2E)
#define ADC_DATA8_OFFSET 0x170
#define ADC_DATA9_OFFSET 0x174
#define ADC_DATA10_OFFSET 0x178
#define ADC_DATA11_OFFSET 0x17c
#define ADC_CHAN8_INTR_OFFSET 0x140
#define ADC_CHAN9_INTR_OFFSET 0x144
#define ADC_CHAN10_INTR_OFFSET 0x148
#define ADC_CHAN11_INTR_OFFSET 0x14c
#else
#define ADC_DATA8_OFFSET 0x60
#define ADC_DATA9_OFFSET 0x70
#define ADC_CHAN8_INTR_OFFSET 0x120
#define ADC_CHAN9_INTR_OFFSET 0x124
#endif
/* S2, S2L and S3 */
#define ADC_STATUS_OFFSET 0x000
#define ADC_SLOT_NUM_OFFSET 0x00c
#define ADC_SLOT_PERIOD_OFFSET 0x010
#define ADC_CTRL_INTR_TABLE_OFFSET 0x044
#define ADC_DATA_INTR_TABLE_OFFSET 0x048
#define ADC_FIFO_INTR_TABLE_OFFSET 0x04c
#define ADC_ERR_STATUS_OFFSET 0x050
#define ADC_SLOT_CTRL_0_OFFSET 0x100
#define ADC_SLOT_CTRL_1_OFFSET 0x104
#define ADC_SLOT_CTRL_2_OFFSET 0x108
#define ADC_SLOT_CTRL_3_OFFSET 0x10c
#define ADC_SLOT_CTRL_4_OFFSET 0x110
#define ADC_SLOT_CTRL_5_OFFSET 0x114
#define ADC_SLOT_CTRL_6_OFFSET 0x118
#define ADC_SLOT_CTRL_7_OFFSET 0x11c
#define ADC_FIFO_CTRL_0_OFFSET 0x180
#define ADC_FIFO_CTRL_1_OFFSET 0x184
#define ADC_FIFO_CTRL_2_OFFSET 0x188
#define ADC_FIFO_CTRL_3_OFFSET 0x18C
#define ADC_FIFO_CTRL_OFFSET 0x190
#define ADC_FIFO_STATUS_0_OFFSET 0x1a0
#define ADC_FIFO_STATUS_1_OFFSET 0x1a4
#define ADC_FIFO_STATUS_2_OFFSET 0x1a8
#define ADC_FIFO_STATUS_3_OFFSET 0x1ac
#define ADC_EC_ADC_OFFSET 0x1C0
#define ADC_EC_REFVAL_OFFSET 0x1C4
#define ADC_EC_RESHAPE_OFFSET 0x1C8
#define ADC_FIFO_DATA0_OFFSET 0x200
#define ADC_FIFO_DATA1_OFFSET 0x280
#define ADC_FIFO_DATA2_OFFSET 0x300
#define ADC_FIFO_DATA3_OFFSET 0x380
/* A7 */
#define ADC_DATA4_SAMPLE0_OFFSET 0x60
#define ADC_DATA4_SAMPLE1_OFFSET 0x64
#define ADC_DATA4_SAMPLE2_OFFSET 0x68
#define ADC_DATA4_SAMPLE3_OFFSET 0x6c
#define ADC_DATA5_SAMPLE0_OFFSET 0x70
#define ADC_DATA5_SAMPLE1_OFFSET 0x74
#define ADC_DATA5_SAMPLE2_OFFSET 0x78
#define ADC_DATA5_SAMPLE3_OFFSET 0x5c
#define ADC_CONTROL_REG ADC_REG(ADC_CONTROL_OFFSET)
#define ADC_COUNTER_REG ADC_REG(ADC_COUNTER_OFFSET)
#define ADC_ENABLE_REG ADC_REG(ADC_ENABLE_OFFSET)
#define ADC_DATA0_REG ADC_REG(ADC_DATA0_OFFSET)
#define ADC_DATA1_REG ADC_REG(ADC_DATA1_OFFSET)
#define ADC_DATA2_REG ADC_REG(ADC_DATA2_OFFSET)
#define ADC_DATA3_REG ADC_REG(ADC_DATA3_OFFSET)
#define ADC_DATA4_REG ADC_REG(ADC_DATA4_OFFSET)
#define ADC_DATA5_REG ADC_REG(ADC_DATA5_OFFSET)
#define ADC_DATA6_REG ADC_REG(ADC_DATA6_OFFSET)
#define ADC_DATA7_REG ADC_REG(ADC_DATA7_OFFSET)
#define ADC_DATA8_REG ADC_REG(ADC_DATA8_OFFSET)
#define ADC_DATA9_REG ADC_REG(ADC_DATA9_OFFSET)
#define ADC_CHAN0_INTR_REG ADC_REG(ADC_CHAN0_INTR_OFFSET)
#define ADC_CHAN1_INTR_REG ADC_REG(ADC_CHAN1_INTR_OFFSET)
#define ADC_CHAN2_INTR_REG ADC_REG(ADC_CHAN2_INTR_OFFSET)
#define ADC_CHAN3_INTR_REG ADC_REG(ADC_CHAN3_INTR_OFFSET)
#define ADC_CHAN4_INTR_REG ADC_REG(ADC_CHAN4_INTR_OFFSET)
#define ADC_CHAN5_INTR_REG ADC_REG(ADC_CHAN5_INTR_OFFSET)
#define ADC_CHAN6_INTR_REG ADC_REG(ADC_CHAN6_INTR_OFFSET)
#define ADC_CHAN7_INTR_REG ADC_REG(ADC_CHAN7_INTR_OFFSET)
#define ADC_CHAN8_INTR_REG ADC_REG(ADC_CHAN8_INTR_OFFSET)
#define ADC_CHAN9_INTR_REG ADC_REG(ADC_CHAN9_INTR_OFFSET)
#define ADC_DATA4_SAMPLE0_REG ADC_REG(ADC_DATA4_SAMPLE0_OFFSET)
#define ADC_DATA4_SAMPLE1_REG ADC_REG(ADC_DATA4_SAMPLE1_OFFSET)
#define ADC_DATA4_SAMPLE2_REG ADC_REG(ADC_DATA4_SAMPLE2_OFFSET)
#define ADC_DATA4_SAMPLE3_REG ADC_REG(ADC_DATA4_SAMPLE3_OFFSET)
#define ADC_DATA5_SAMPLE0_REG ADC_REG(ADC_DATA5_SAMPLE0_OFFSET)
#define ADC_DATA5_SAMPLE1_REG ADC_REG(ADC_DATA5_SAMPLE1_OFFSET)
#define ADC_DATA5_SAMPLE2_REG ADC_REG(ADC_DATA5_SAMPLE2_OFFSET)
#define ADC_DATA5_SAMPLE3_REG ADC_REG(ADC_DATA5_SAMPLE3_OFFSET)
/* valid only for S2/S2E/S2L/S3/S3L */
#define ADC_STATUS_REG ADC_REG(ADC_STATUS_OFFSET)
#define ADC_SLOT_NUM_REG ADC_REG(ADC_SLOT_NUM_OFFSET)
#define ADC_SLOT_PERIOD_REG ADC_REG(ADC_SLOT_PERIOD_OFFSET)
#define ADC_CTRL_INTR_TABLE_REG ADC_REG(ADC_CTRL_INTR_TABLE_OFFSET)
#define ADC_DATA_INTR_TABLE_REG ADC_REG(ADC_DATA_INTR_TABLE_OFFSET)
#define ADC_FIFO_INTR_TABLE_REG ADC_REG(ADC_FIFO_INTR_TABLE_OFFSET)
#define ADC_ERR_STATUS_REG ADC_REG(ADC_ERR_STATUS_OFFSET)
#define ADC_SLOT_CTRL_0_REG ADC_REG(ADC_SLOT_CTRL_0_OFFSET)
#define ADC_SLOT_CTRL_1_REG ADC_REG(ADC_SLOT_CTRL_1_OFFSET)
#define ADC_SLOT_CTRL_2_REG ADC_REG(ADC_SLOT_CTRL_2_OFFSET)
#define ADC_SLOT_CTRL_3_REG ADC_REG(ADC_SLOT_CTRL_3_OFFSET)
#define ADC_SLOT_CTRL_4_REG ADC_REG(ADC_SLOT_CTRL_4_OFFSET)
#define ADC_SLOT_CTRL_5_REG ADC_REG(ADC_SLOT_CTRL_5_OFFSET)
#define ADC_SLOT_CTRL_6_REG ADC_REG(ADC_SLOT_CTRL_6_OFFSET)
#define ADC_SLOT_CTRL_7_REG ADC_REG(ADC_SLOT_CTRL_7_OFFSET)
#define ADC_FIFO_CTRL_0_REG ADC_REG(ADC_FIFO_CTRL_0_OFFSET)
#define ADC_FIFO_CTRL_1_REG ADC_REG(ADC_FIFO_CTRL_1_OFFSET)
#define ADC_FIFO_CTRL_2_REG ADC_REG(ADC_FIFO_CTRL_2_OFFSET)
#define ADC_FIFO_CTRL_3_REG ADC_REG(ADC_FIFO_CTRL_3_OFFSET)
#define ADC_FIFO_CTRL_REG ADC_REG(ADC_FIFO_CTRL_OFFSET)
#define ADC_FIFO_STATUS_0_REG ADC_REG(ADC_FIFO_STATUS_0_OFFSET)
#define ADC_FIFO_STATUS_1_REG ADC_REG(ADC_FIFO_STATUS_1_OFFSET)
#define ADC_FIFO_STATUS_2_REG ADC_REG(ADC_FIFO_STATUS_2_OFFSET)
#define ADC_FIFO_STATUS_3_REG ADC_REG(ADC_FIFO_STATUS_3_OFFSET)
#define ADC_EC_ADC_REG ADC_REG(ADC_EC_ADC_OFFSET)
#define ADC_EC_REFVAL_REG ADC_REG(ADC_EC_REFVAL_OFFSET)
#define ADC_EC_RESHAPE_REG ADC_REG(ADC_EC_RESHAPE_OFFSET)
#define ADC_FIFO_DATA0_REG ADC_REG(ADC_FIFO_DATA0_OFFSET)
#define ADC_FIFO_DATA1_REG ADC_REG(ADC_FIFO_DATA1_OFFSET)
#define ADC_FIFO_DATA2_REG ADC_REG(ADC_FIFO_DATA2_OFFSET)
#define ADC_FIFO_DATA3_REG ADC_REG(ADC_FIFO_DATA3_OFFSET)
#define ADC_DATA10_REG ADC_REG(ADC_DATA10_OFFSET)
#define ADC_DATA11_REG ADC_REG(ADC_DATA11_OFFSET)
#define ADC_CHAN10_INTR_REG ADC_REG(ADC_CHAN10_INTR_OFFSET)
#define ADC_CHAN11_INTR_REG ADC_REG(ADC_CHAN11_INTR_OFFSET)
#if (CHIP_REV == A7L)
#error "ADC_DATA_REG/ADC_CHAN_INTR_REG(ch) Not Implemented"
#else
#define ADC_DATA_OFFSET(ch) (ADC_DATA0_OFFSET + (ch) * 4)
#define ADC_DATA_REG(ch) ADC_REG(ADC_DATA_OFFSET(ch))
#define ADC_FIFO_CTRL_X_OFFSET(fifoNo) (ADC_FIFO_CTRL_0_OFFSET + (fifoNo) * 4)
#define ADC_FIFO_CTRL_X_REG(fifoNo) ADC_REG(ADC_FIFO_CTRL_X_OFFSET(fifoNo))
#define ADC_CHAN_INTR_OFFSET(ch) (ADC_CHAN0_INTR_OFFSET + (ch) * 4)
#define ADC_CHAN_INTR_REG(ch) ADC_REG(ADC_CHAN_INTR_OFFSET(ch))
#endif
#define ADC16_CTRL_OFFSET 0x198
#define ADC16_CTRL_REG RCT_REG(ADC16_CTRL_OFFSET)
/* ADC_CONTROL_REG */
#define ADC_CONTROL_GYRO_SAMPLE_MODE 0x08
/* valid only for S2/S2E/S2L/S3/S3L */
#define ADC_CONTROL_RESET 0x01
#define ADC_FIFO_OVER_INT_EN (0x1 << 31)
#define ADC_FIFO_UNDR_INT_EN (0x1 << 30)
#define ADC_FIFO_DEPTH 0x80
#define ADC_FIFO_TH (((ADC_FIFO_DEPTH >> 2)-1) << 16)
#define ADC_FIFO_CLEAR 0x1
#define ADC_FIFO_ID_SHIFT 12
#define ADC_FIFO_CONTROL_CLEAR 0x01
#define ADC_FIFO_NUMBER 0x04
#define ADC_CTRL_SCALER_POWERDOWN 0x100
#define ADC_CTRL_POWERDOWN 0x2
#define ADC_CTRL_CLK_SOURCE_SCALER 0x0
#define ADC_CTRL_CLK_SOURCE_AUDIO 0x1
#if (CHIP_REV == A5S)
#define ADC_CONTROL_MODE 0x04
#define ADC_CONTROL_ENABLE 0x01
#define ADC_CONTROL_START 0x02
#else
#define ADC_CONTROL_MODE 0x02
#define ADC_CONTROL_ENABLE 0x04
#define ADC_CONTROL_START 0x08
#endif
#define ADC_CONTROL_STATUS 0x01
#define ADC_STATUS 0x01
#define ADC_STATUS_SAMPLING_DONE 0x02
#if (CHIP_REV == A5S)
#define ADC_EN_HI(x) ((x) << 31)
#define ADC_EN_LO(x) ((x) << 30)
#else
#define ADC_EN_HI(x) ((x) << 31)
#define ADC_EN_LO(x) ((x) << 31)
#endif
#define ADC_VAL_HI(x) (((x) & 0xfff) << 16)
#define ADC_VAL_LO(x) ((x) & 0xfff)
/* ==========================================================================*/
#define ADC_MAX_SLOT_NUMBER 8
#define ADC_CH0 (1 << 0)
#define ADC_CH1 (1 << 1)
#define ADC_CH2 (1 << 2)
#define ADC_CH3 (1 << 3)
#define ADC_CH4 (1 << 4)
#define ADC_CH5 (1 << 5)
#define ADC_CH6 (1 << 6)
#define ADC_CH7 (1 << 7)
#define ADC_CH8 (1 << 8)
#define ADC_CH9 (1 << 9)
#define ADC_CH10 (1 << 10)
#define ADC_CH11 (1 << 11)
enum {
AMBADC_ONESHOT = 0,
AMBADC_CONTINUOUS,
};
struct ambadc_host {
struct device *dev;
u32 irq;
u32 clk;
bool polling_mode;
bool keep_start;
bool fifo_mode;
struct delayed_work work;
};
struct ambadc_client;
typedef int (*ambadc_client_callback)(struct ambadc_client *client,
u32 ch, u32 level);
typedef int (*ambadc_read_level)(u32 ch);
struct ambadc_client {
struct device *dev;
struct ambadc_host *host;
struct list_head node;
u32 threshold[ADC_NUM_CHANNELS];
u32 mode;
ambadc_client_callback callback;
};
extern struct ambadc_client *ambarella_adc_register_client(struct device *dev,
u32 mode, ambadc_client_callback callback);
extern void ambarella_adc_unregister_client(struct ambadc_client *client);
extern int ambarella_adc_set_threshold(struct ambadc_client *client,
u32 ch, u32 low, u32 high);
extern int ambarella_adc_read_level(u32 ch);
#endif /* __PLAT_AMBARELLA_ADC_H__ */