summaryrefslogtreecommitdiff
path: root/drivers/power/mxs/ddi_bc_init.c
blob: c93f8969f92c05ce6e207d0efcd4ebe8d5b356c1 (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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/*
 * Copyright (C) 2010 Freescale Semiconductor, 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 "ddi_bc_internal.h"


/* addtogroup ddi_bc */
/*  @{ */
/*  */
/* Copyright (c) 2004-2005 SigmaTel, Inc. */
/*  */
/* file       ddi_bc_init.c */
/* brief      Contains the Battery Charger initialization function. */
/* date       06/2005 */
/*  */
/*  This file contains Battery Charger initialization function. */
/*  */



/* Includes and external references */

#include <mach/ddi_bc.h>
#include "ddi_bc_internal.h"


/* Code */



/* brief Initialize the Battery Charger. */
/*  */
/* fntype Function */
/*  */
/*  This function initializes the Battery Charger. */
/*  */
/* param[in]  pCfg  A pointer to the new configuration. */
/*  */
/* retval  DDI_BC_STATUS_SUCCESS */
/*              If the operation succeeded. */
/* retval  DDI_BC_STATUS_ALREADY_INITIALIZED */
/*              If the Battery Charger is already initialized. */
/* retval  DDI_BC_STATUS_HARDWARE_DISABLED */
/*              If the Battery Charger hardware is disabled by a laser fuse. */
/* retval  DDI_BC_STATUS_BAD_BATTERY_MODE */
/*              If the power supply is set up for a non-rechargeable battery. */
/* retval  DDI_BC_STATUS_CLOCK_GATE_CLOSED */
/*              If the clock gate for the power supply registers is closed. */
/* retval  DDI_BC_STATUS_CFG_BAD_CHARGING_VOLTAGE */
/*              If the charging voltage is not either 4100 or 4200. */
/* retval  DDI_BC_STATUS_CFG_BAD_BATTERY_TEMP_CHANNEL */
/*              If the LRADC channel number for monitoring battery temperature */
/*              is bad. */
/*  */

ddi_bc_Status_t ddi_bc_Init(ddi_bc_Cfg_t *pCfg)
{

	/* -------------------------------------------------------------------------- */
	/* We can only be initialized if we're in the Uninitialized state. */
	/* -------------------------------------------------------------------------- */

	if (g_ddi_bc_State != DDI_BC_STATE_UNINITIALIZED) {
		return DDI_BC_STATUS_ALREADY_INITIALIZED;
	}
	/* -------------------------------------------------------------------------- */
	/* Check if the battery charger hardware has been disabled by laser fuse. */
	/* -------------------------------------------------------------------------- */

	if (!ddi_power_GetBatteryChargerEnabled())
		return DDI_BC_STATUS_HARDWARE_DISABLED;

	/* -------------------------------------------------------------------------- */
	/* Check if the power supply has been set up for a non-rechargeable battery. */
	/* -------------------------------------------------------------------------- */

	switch (ddi_power_GetBatteryMode()) {

	case DDI_POWER_BATT_MODE_LIION:
		break;

		/* TODO: we'll need to do NiMH also */
	default:
		return DDI_BC_STATUS_BAD_BATTERY_MODE;
		/* break; */

	}

	/* -------------------------------------------------------------------------- */
	/* Make sure that the clock gate has been opened for the power supply */
	/* registers. If not, then none of our writes to those registers will */
	/* succeed, which will kind of slow us down... */
	/* -------------------------------------------------------------------------- */

	if (ddi_power_GetPowerClkGate()) {
		return DDI_BC_STATUS_CLOCK_GATE_CLOSED;
	}
	/* -------------------------------------------------------------------------- */
	/* Check the incoming configuration for nonsense. */
	/* -------------------------------------------------------------------------- */

	/*  */
	/* Only permitted charging voltage: 4200mV. */
	/*  */

	if (pCfg->u16ChargingVoltage != DDI_BC_LIION_CHARGING_VOLTAGE) {
		return DDI_BC_STATUS_CFG_BAD_CHARGING_VOLTAGE;
	}
	/*  */
	/* There are 8 LRADC channels. */
	/*  */

	if (pCfg->u8BatteryTempChannel > 7) {
		return DDI_BC_STATUS_CFG_BAD_BATTERY_TEMP_CHANNEL;
	}
	/* -------------------------------------------------------------------------- */
	/* Accept the configuration. */
	/* -------------------------------------------------------------------------- */

	/* -------------------------------------------------------------------------- */
	/*  ddi_bc_Cfg_t.u16ChargingThresholdCurrent is destined for the */
	/*  register field HW_POWER_BATTCHRG.STOP_ILIMIT.  This 4-bit field */
	/*  is unevenly quantized to provide a useful range of currents.  A */
	/*  side effect of the quantization is that the field can only be */
	/*  set to certain unevenly-spaced values. */
	/*  */
	/*  Here, we use the two functions that manipulate the register field */
	/*  to adjust u16ChargingThresholdCurrent to match the quantized value. */
	/* -------------------------------------------------------------------------- */
	pCfg->u16ChargingThresholdCurrent =
	    ddi_power_ExpressibleCurrent(pCfg->u16ChargingThresholdCurrent);

	/* -------------------------------------------------------------------------- */
	/*  ...similar situation with ddi_bc_Cfg_t.u16BatteryTempSafeCurrent and */
	/*  u16DieTempSafeCurrent. */
	/* -------------------------------------------------------------------------- */
	pCfg->u16BatteryTempSafeCurrent =
	    ddi_power_ExpressibleCurrent(pCfg->u16BatteryTempSafeCurrent);
	pCfg->u16DieTempSafeCurrent =
	    ddi_power_ExpressibleCurrent(pCfg->u16DieTempSafeCurrent);

	g_ddi_bc_Configuration = *pCfg;

	/* -------------------------------------------------------------------------- */
	/* Turn the charger hardware off. This is a very important initial condition */
	/* because we only flip the power switch on the hardware when we make */
	/* transitions. Baseline, it needs to be off. */
	/* -------------------------------------------------------------------------- */

	ddi_power_SetChargerPowered(0);

	/* -------------------------------------------------------------------------- */
	/* Reset the current ramp. This will jam the current to zero and power off */
	/* the charging hardware. */
	/* -------------------------------------------------------------------------- */

	ddi_bc_RampReset();

	/* -------------------------------------------------------------------------- */
	/* Move to the Disabled state. */
	/* -------------------------------------------------------------------------- */

	g_ddi_bc_State = DDI_BC_STATE_DISABLED;

	/* -------------------------------------------------------------------------- */
	/* Return success. */
	/* -------------------------------------------------------------------------- */
#ifdef CONFIG_POWER_SUPPLY_DEBUG
	printk("%s: success\n", __func__);
#endif
	return DDI_BC_STATUS_SUCCESS;

}


/* End of file */

/*  @} */