summaryrefslogtreecommitdiffstats
path: root/firmware/target/arm/imx233/lradc-imx233.c
blob: 432d1c1035749421a9d42b3afb44bbf263ac8a52 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 * $Id$
 *
 * Copyright (C) 2011 by Amaury Pouly
 *
 * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ****************************************************************************/
#include "system.h"
#include "system-target.h"
#include "lradc-imx233.h"
#include "kernel-imx233.h"

/* channels */
static struct channel_arbiter_t channel_arbiter;
/* delay channels */
static struct channel_arbiter_t delay_arbiter;

void imx233_lradc_setup_channel(int channel, bool div2, bool acc, int nr_samples, int src)
{
    __REG_CLR(HW_LRADC_CHx(channel)) = HW_LRADC_CHx__NUM_SAMPLES_BM | HW_LRADC_CHx__ACCUMULATE;
    __REG_SET(HW_LRADC_CHx(channel)) = nr_samples << HW_LRADC_CHx__NUM_SAMPLES_BP |
        acc << HW_LRADC_CHx__ACCUMULATE;
    if(div2)
        __REG_SET(HW_LRADC_CTRL2) = HW_LRADC_CTRL2__DIVIDE_BY_TWO(channel);
    else
        __REG_CLR(HW_LRADC_CTRL2) = HW_LRADC_CTRL2__DIVIDE_BY_TWO(channel);
    __REG_CLR(HW_LRADC_CTRL4) = HW_LRADC_CTRL4__LRADCxSELECT_BM(channel);
    __REG_SET(HW_LRADC_CTRL4) = src << HW_LRADC_CTRL4__LRADCxSELECT_BP(channel);
}

void imx233_lradc_setup_delay(int dchan, int trigger_lradc, int trigger_delays,
    int loop_count, int delay)
{
    HW_LRADC_DELAYx(dchan) =
        trigger_lradc << HW_LRADC_DELAYx__TRIGGER_LRADCS_BP |
        trigger_delays << HW_LRADC_DELAYx__TRIGGER_DELAYS_BP |
        loop_count << HW_LRADC_DELAYx__LOOP_COUNT_BP |
        delay << HW_LRADC_DELAYx__DELAY_BP;
}

void imx233_lradc_kick_channel(int channel)
{
    __REG_CLR(HW_LRADC_CTRL1) = HW_LRADC_CTRL1__LRADCx_IRQ(channel);
    __REG_SET(HW_LRADC_CTRL0) = HW_LRADC_CTRL0__SCHEDULE(channel);
}

void imx233_lradc_kick_delay(int dchan)
{
    __REG_SET(HW_LRADC_DELAYx(dchan)) = HW_LRADC_DELAYx__KICK;
}

void imx233_lradc_wait_channel(int channel)
{
    /* wait for completion */
    while(!(HW_LRADC_CTRL1 & HW_LRADC_CTRL1__LRADCx_IRQ(channel)))
        yield();
}

int imx233_lradc_read_channel(int channel)
{
    return __XTRACT_EX(HW_LRADC_CHx(channel), HW_LRADC_CHx__VALUE);
}

void imx233_lradc_clear_channel(int channel)
{
    __REG_CLR(HW_LRADC_CHx(channel)) = HW_LRADC_CHx__VALUE_BM;
}

int imx233_lradc_acquire_channel(int timeout)
{
    return arbiter_acquire(&channel_arbiter, timeout);
}

void imx233_lradc_release_channel(int chan)
{
    return arbiter_release(&channel_arbiter, chan);
}

void imx233_lradc_reserve_channel(int channel)
{
    return arbiter_reserve(&channel_arbiter, channel);
}

int imx233_lradc_acquire_delay(int timeout)
{
    return arbiter_acquire(&delay_arbiter, timeout);
}

void imx233_lradc_release_delay(int chan)
{
    return arbiter_release(&delay_arbiter, chan);
}

void imx233_lradc_reserve_delay(int channel)
{
    return arbiter_reserve(&delay_arbiter, channel);
}

int imx233_lradc_sense_die_temperature(int nmos_chan, int pmos_chan)
{
    // mux sensors
    __REG_CLR(HW_LRADC_CTRL2) = HW_LRADC_CTRL2__TEMPSENSE_PWD;
    imx233_lradc_clear_channel(nmos_chan);
    imx233_lradc_clear_channel(pmos_chan);
    // schedule both channels
    imx233_lradc_kick_channel(nmos_chan);
    imx233_lradc_kick_channel(pmos_chan);
    // wait completion
    imx233_lradc_wait_channel(nmos_chan);
    imx233_lradc_wait_channel(pmos_chan);
    // mux sensors
    __REG_SET(HW_LRADC_CTRL2) = HW_LRADC_CTRL2__TEMPSENSE_PWD;
    // do the computation
    int diff = imx233_lradc_read_channel(nmos_chan) - imx233_lradc_read_channel(pmos_chan);
    // return diff * 1.012 / 4
    return (diff * 1012) / 4000;
}

void imx233_lradc_setup_battery_conversion(bool automatic, unsigned long scale_factor)
{
    __REG_CLR(HW_LRADC_CONVERSION) = HW_LRADC_CONVERSION__SCALE_FACTOR_BM;
    __REG_SET(HW_LRADC_CONVERSION) = scale_factor;
    if(automatic)
        __REG_SET(HW_LRADC_CONVERSION) = HW_LRADC_CONVERSION__AUTOMATIC;
    else
        __REG_CLR(HW_LRADC_CONVERSION) = HW_LRADC_CONVERSION__AUTOMATIC;
}

int imx233_lradc_read_battery_voltage(void)
{
    return __XTRACT(HW_LRADC_CONVERSION, SCALED_BATT_VOLTAGE);
}

void imx233_lradc_init(void)
{
    arbiter_init(&channel_arbiter, HW_LRADC_NUM_CHANNELS);
    arbiter_init(&delay_arbiter, HW_LRADC_NUM_DELAYS);
    // enable block
    imx233_reset_block(&HW_LRADC_CTRL0);
    // disable ground ref
    __REG_CLR(HW_LRADC_CTRL0) = HW_LRADC_CTRL0__ONCHIP_GROUNDREF;
    // disable temperature sensors
    __REG_CLR(HW_LRADC_CTRL2) = HW_LRADC_CTRL2__TEMP_SENSOR_IENABLE0 |
        HW_LRADC_CTRL2__TEMP_SENSOR_IENABLE1;
    __REG_SET(HW_LRADC_CTRL2) = HW_LRADC_CTRL2__TEMPSENSE_PWD;
    // set frequency
    __REG_CLR(HW_LRADC_CTRL3) = HW_LRADC_CTRL3__CYCLE_TIME_BM;
    __REG_SET(HW_LRADC_CTRL3) = HW_LRADC_CTRL3__CYCLE_TIME__6MHz;
}