LM3642 Initial Commit : Synchronous Boost Single LED Flash Driver
[windows-iot-driver/drivers.git] / LM3642 / TxnwLedLM3642 / Device.c
1 /*++\r
2 Copyright (c) Texas Instruments Inc. All Rights Reserved.\r
3 Sample code for LED FLASH LM3642.\r
4 \r
5 The MIT License (MIT)\r
6 \r
7 Permission is hereby granted, free of charge, to any person obtaining a copy\r
8 of this software and associated documentation files (the "Software"), to deal\r
9 in the Software without restriction, including without limitation the rights\r
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
11 copies of the Software, and to permit persons to whom the Software is\r
12 furnished to do so, subject to the following conditions:\r
13 \r
14 The above copyright notice and this permission notice shall be included in\r
15 all copies or substantial portions of the Software.\r
16 \r
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ORdsfsdrfdsafsdf\r
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
23 THE SOFTWARE.\r
24 \r
25 Module Name:\r
26 \r
27 device.c - Device handling events for example driver.\r
28 \r
29 Abstract:\r
30 \r
31 This file contains the device entry points and callbacks.\r
32 \r
33 Environment:\r
34 \r
35 Kernel-mode Driver Framework\r
36 \r
37 --*/\r
38 \r
39 #include "driver.h"\r
40 #include "device.tmh"\r
41 #include "spb.h"\r
42 #include "public.h"\r
43 \r
44 #ifdef ALLOC_PRAGMA\r
45 #pragma alloc_text(PAGE, OnD0Exit)\r
46 #endif\r
47 \r
48 // LM3642 Registers
49 #define REG_REVISION            0x00
50 #define REG_REVISION_MASK       0x07
52 //IVFM Mode Register
53 #define REG_IVFM_MODE           0x01
54 #define REG_IVFM_MODE_THRESHOLD_MASK    0x1C
56 // Torch Ramp Time Reister
57 #define REG_TORCH_RAMP          0x06
58 #define REG_TORCH_RAMP_UP_TIME_MASK             0x38
59 #define REG_TORCH_RAMP_DN_TIME_MASK             0x07
61 //Flash Freature Register
62 #define REG_FLASH_FEATURE                                       0x08
63 #define REG_FLASH_FEATURE_RAMPTIME_MASK         0x38
64 #define REG_FLASH_FEATURE_RAMPTIME_SHIFT        3
65 #define REG_FLASH_FEATURE_TIMEOUT_MASK          0x07
66 #define REG_FLASH_FEATURE_TIMEOUT_SHIFT         0
68 //Current Control Register
69 #define REG_CURRENT_CTRL                                0x09
70 #define REG_CURRENT_CTRL_FLASH_MASK             0x0F
71 #define REG_CURRENT_CTRL_FLASH_SHIFT    0
72 #define REG_CURRENT_CTRL_TORCH_MASK             0x70
73 #define REG_CURRENT_CTRL_TORCH_SHIFT    4
75 //Enable Register
76 #define REG_ENABLE                              0x0A
77 #define REG_ENABLE_MODE_MASK    0x03
78 #define REG_ENABLE_MODE_SHIFT   0
80 //Flag Registers
81 #define REG_FLAG                0x0B
82 #define REG_FLAG_MASK   0x1F
83 \r
84 \r
85 #define FLED_REG_MODE_ADDR REG_ENABLE\r
86 #define FLED_REG_MODE_MASK REG_ENABLE_MODE_MASK\r
87 #define FLED_REG_MODE_OFF  0\r
88 \r
89 NTSTATUS\r
90 RegUpdateSynchronously(\r
91         IN SPB_CONTEXT *SpbContext,\r
92         IN UCHAR Address,\r
93         IN UCHAR Mask,\r
94         IN UCHAR Data\r
95         )\r
96 {\r
97         NTSTATUS status = STATUS_SUCCESS;\r
98         BYTE rData;\r
100         PAGED_CODE();\r
101 \r
102         status = SpbReadDataSynchronously(SpbContext, Address, &rData, 1);\r
103         if (!NT_SUCCESS(status))\r
104                 return status;\r
105 \r
106         rData &= ~Mask;\r
107         rData |= (Data & Mask);\r
108 \r
109         status = SpbWriteDataSynchronously(SpbContext, Address, &rData, 1);\r
110 \r
111         return status;\r
112 }\r
113 \r
114 NTSTATUS\r
115 OnD0Entry(\r
116         IN WDFDEVICE Device,\r
117         IN WDF_POWER_DEVICE_STATE PreviousState\r
118         )\r
119         /*++\r
120 \r
121         Routine Description:\r
122 \r
123         This routine will power on the hardware\r
124 \r
125         Arguments:\r
126 \r
127         Device - WDF device to power on\r
128         PreviousState - Prior power state\r
129 \r
130         Return Value:\r
131 \r
132         NTSTATUS indicating success or failure\r
133 \r
134         */\r
135 {\r
136         NTSTATUS status = STATUS_SUCCESS;\r
137         PDEVICE_EXTENSION devContext;\r
138 \r
139         devContext = GetDeviceContext(Device);\r
140 \r
141         UNREFERENCED_PARAMETER(PreviousState);\r
142 \r
143         devContext->ServiceInterruptsAfterD0Entry = TRUE;\r
144 \r
145         return status;\r
146 }\r
147 \r
148 NTSTATUS\r
149 OnD0Exit(\r
150         IN WDFDEVICE Device,\r
151         IN WDF_POWER_DEVICE_STATE TargetState\r
152         )\r
153         /*++\r
154 \r
155         Routine Description:\r
156 \r
157         This routine will power down the hardware\r
158 \r
159         Arguments:\r
160 \r
161         Device - WDF device to power off\r
162 \r
163         PreviousState - Prior power state\r
164 \r
165         Return Value:\r
166 \r
167         NTSTATUS indicating success or failure\r
168 \r
169         */\r
170 {\r
171         NTSTATUS status = STATUS_SUCCESS;\r
172         PDEVICE_EXTENSION devContext;\r
173 \r
174         UNREFERENCED_PARAMETER(TargetState);\r
175 \r
176         PAGED_CODE();\r
177 \r
178         devContext = GetDeviceContext(Device);\r
179 \r
180         SPB_CONTEXT *SpbContext = &devContext->I2CContext;\r
181         status = RegUpdateSynchronously(SpbContext, FLED_REG_MODE_ADDR, \r
182                                                                 FLED_REG_MODE_MASK, FLED_REG_MODE_OFF);\r
183         return status;\r
184 }\r
185 \r
186 NTSTATUS\r
187 OnPrepareHardware(\r
188         IN WDFDEVICE FxDevice,\r
189         IN WDFCMRESLIST FxResourcesRaw,\r
190         IN WDFCMRESLIST FxResourcesTranslated\r
191         )\r
192         /*++\r
193 \r
194         Routine Description:\r
195 \r
196         This routine is called by the PnP manager and supplies thie device instance\r
197         with it's SPB resources (CmResourceTypeConnection) needed to find the I2C\r
198         driver.\r
199 \r
200         Arguments:\r
201 \r
202         FxDevice - a handle to the framework device object\r
203         FxResourcesRaw - list of translated hardware resources that\r
204         the PnP manager has assigned to the device\r
205         FxResourcesTranslated - list of raw hardware resources that\r
206         the PnP manager has assigned to the device\r
207 \r
208         Return Value:\r
209 \r
210         NTSTATUS indicating sucess or failure\r
211 \r
212         --*/\r
213 {\r
214         NTSTATUS status;\r
215         PCM_PARTIAL_RESOURCE_DESCRIPTOR res;\r
216         PDEVICE_EXTENSION devContext;\r
217         ULONG resourceCount;\r
218         ULONG i;\r
219 \r
220         UNREFERENCED_PARAMETER(FxResourcesRaw);\r
222         PAGED_CODE();\r
223 \r
224         status = STATUS_INSUFFICIENT_RESOURCES;\r
225         devContext = GetDeviceContext(FxDevice);\r
226         resourceCount = WdfCmResourceListGetCount(FxResourcesTranslated);\r
227 \r
228         for (i = 0; i < resourceCount; i++)\r
229         {\r
230                 res = WdfCmResourceListGetDescriptor(FxResourcesTranslated, i);\r
231 \r
232                 if (res->Type == CmResourceTypeConnection &&\r
233                         res->u.Connection.Class == CM_RESOURCE_CONNECTION_CLASS_SERIAL &&\r
234                         res->u.Connection.Type == CM_RESOURCE_CONNECTION_TYPE_SERIAL_I2C)\r
235                 {\r
236                         devContext->I2CContext.I2cResHubId.LowPart =\r
237                                 res->u.Connection.IdLowPart;\r
238                         devContext->I2CContext.I2cResHubId.HighPart =\r
239                                 res->u.Connection.IdHighPart;\r
240 \r
241                         status = STATUS_SUCCESS;\r
242                 }\r
243         }\r
244 \r
245         if (!NT_SUCCESS(status))\r
246                 goto exit;\r
247 \r
248         //\r
249         // Initialize Spb so the driver can issue reads/writes\r
250         //\r
251         status = SpbTargetInitialize(FxDevice, &devContext->I2CContext);\r
252 \r
253         if (!NT_SUCCESS(status))\r
254                 goto exit;\r
255 \r
256         // \r
257         // Read Device Id - LM3642 ID should be 000\r
258         // \r
259         BYTE rData;\r
260         SPB_CONTEXT *SpbContext = &devContext->I2CContext;\r
261         status = SpbReadDataSynchronously(SpbContext, REG_REVISION, &rData, 1);\r
262         if (!NT_SUCCESS(status))\r
263                 goto exit;\r
264 \r
265         // StandBy MODE Set or Disable\r
266         status = RegUpdateSynchronously(SpbContext, FLED_REG_MODE_ADDR,\r
267                 FLED_REG_MODE_MASK, FLED_REG_MODE_OFF);\r
268         // \r
269         // Add additional chip initialize code here if it is needed\r
270         // such as TX-pin, IVFM Levels/Hysteresis, Selection etc \r
271 \r
272 exit:\r
273 \r
274         return status;\r
275 }\r
276 \r
277 NTSTATUS\r
278 OnReleaseHardware(\r
279         IN WDFDEVICE FxDevice,\r
280         IN WDFCMRESLIST FxResourcesTranslated\r
281         )\r
282         /*++\r
283 \r
284         Routine Description:\r
285 \r
286         This routine cleans up any resources provided.\r
287 \r
288         Arguments:\r
289 \r
290         FxDevice - a handle to the framework device object\r
291         FxResourcesRaw - list of translated hardware resources that\r
292         the PnP manager has assigned to the device\r
293         FxResourcesTranslated - list of raw hardware resources that\r
294         the PnP manager has assigned to the device\r
295 \r
296         Return Value:\r
297 \r
298         NTSTATUS indicating sucesss or failure\r
299 \r
300         --*/\r
301 {\r
302         NTSTATUS status;\r
303         PDEVICE_EXTENSION devContext;\r
304         SPB_CONTEXT *SpbContext;\r
305         UNREFERENCED_PARAMETER(FxResourcesTranslated);\r
307         PAGED_CODE();\r
308 \r
309         devContext = GetDeviceContext(FxDevice);\r
310 \r
311         //Standby Mode or Disable\r
312         SpbContext = &devContext->I2CContext;\r
313         status = RegUpdateSynchronously(SpbContext, FLED_REG_MODE_ADDR,\r
314                                                                         FLED_REG_MODE_MASK, FLED_REG_MODE_OFF);\r
315         if (!NT_SUCCESS(status))\r
316         {\r
317                 return status;\r
318         }\r
319 \r
320         SpbTargetDeinitialize(FxDevice, &GetDeviceContext(FxDevice)->I2CContext);\r
321 \r
322         return status;\r
323 }\r
324 \r
325 \r
326 \r
327 VOID\r
328 OnDeviceControl(\r
329         IN WDFQUEUE Queue,\r
330         IN WDFREQUEST Request,\r
331         IN size_t OutputBufferLength,\r
332         IN size_t InputBufferLength,\r
333         IN ULONG IoControlCode\r
334         )\r
335         /*++\r
336 \r
337         Routine Description:\r
338 \r
339         This event is called when the framework receives\r
340         IRP_MJ_INTERNAL DEVICE_CONTROL requests from the system.\r
341 \r
342         Arguments:\r
343 \r
344         Queue - Handle to the framework queue object that is associated\r
345         with the I/O request.\r
346 \r
347         Request - Handle to a framework request object.\r
348 \r
349         OutputBufferLength - length of the request's output buffer,\r
350         if an output buffer is available.\r
351 \r
352         InputBufferLength - length of the request's input buffer,\r
353         if an input buffer is available.\r
354 \r
355         IoControlCode - the driver-defined or system-defined I/O control code\r
356         (IOCTL) that is associated with the request.\r
357 \r
358         Return Value:\r
359 \r
360         None, status is indicated when completing the request\r
361 \r
362         --*/\r
363 {\r
364         NTSTATUS status = STATUS_SUCCESS;\r
365         PDEVICE_EXTENSION devContext;\r
366         WDFDEVICE device;\r
367         BOOLEAN requestPending;\r
368         BYTE rData = 0, wData = 0;\r
369         ULONG* inputVal;\r
370         ULONG* retVal;\r
371         SPB_CONTEXT *SpbContext;\r
372         UNREFERENCED_PARAMETER(OutputBufferLength);\r
373         UNREFERENCED_PARAMETER(InputBufferLength);\r
375         PAGED_CODE();\r
376 \r
377         device = WdfIoQueueGetDevice(Queue);\r
378         devContext = GetDeviceContext(device);\r
379         requestPending = FALSE;\r
380 \r
381         SpbContext = &devContext->I2CContext;\r
382 \r
383         WdfRequestRetrieveInputBuffer(Request, sizeof(ULONG), (void**)&inputVal, NULL);\r
384         WdfRequestRetrieveOutputBuffer(Request, sizeof(ULONG), (void**)&retVal, NULL);\r
385         wData = (*inputVal) & 0xff;\r
386         \r
387         switch (IoControlCode) {\r
388 \r
389         case IOCTL_FLED_DEVID:\r
390                 status = SpbReadDataSynchronously(SpbContext, REG_REVISION, &rData, 1);\r
391                 if (!NT_SUCCESS(status))\r
392                         goto end;\r
393                 *retVal = (ULONG)(rData & REG_REVISION_MASK);\r
394                 break;\r
395 \r
396         case  IOCTL_FLED_MODE:\r
397                 status = SpbUpdateSynchronously(SpbContext,\r
398                         REG_ENABLE, REG_ENABLE_MODE_MASK,\r
399                         wData << REG_ENABLE_MODE_SHIFT);\r
400                 if (!NT_SUCCESS(status))\r
401                         goto end;\r
402                 break;\r
403 \r
404         case  IOCTL_FLED_STATUS:\r
405                 status = SpbReadDataSynchronously(SpbContext, REG_FLAG, &rData, 1);\r
406                 if (!NT_SUCCESS(status))\r
407                         goto end;\r
408                 *retVal = (ULONG)(rData & REG_FLAG_MASK);\r
409                 break;\r
410 \r
411         case  IOCTL_FLED_BRT_FLASH:\r
412                 status = SpbUpdateSynchronously(SpbContext,\r
413                         REG_CURRENT_CTRL, REG_CURRENT_CTRL_FLASH_MASK,\r
414                         wData << REG_CURRENT_CTRL_FLASH_SHIFT);\r
415                 if (!NT_SUCCESS(status))\r
416                         goto end;\r
417                 break;\r
418 \r
419         case  IOCTL_FLED_BRT_TORCH:\r
420                 status = SpbUpdateSynchronously(SpbContext,\r
421                         REG_CURRENT_CTRL, REG_CURRENT_CTRL_TORCH_MASK,\r
422                         wData << REG_CURRENT_CTRL_TORCH_SHIFT);\r
423                 if (!NT_SUCCESS(status))\r
424                         goto end;\r
425                 break;
426                 \r
427         case  IOCTL_FLED_FLASH_TOUT:\r
428                 status = SpbUpdateSynchronously(SpbContext,\r
429                         REG_FLASH_FEATURE, REG_FLASH_FEATURE_TIMEOUT_MASK,\r
430                         wData << REG_FLASH_FEATURE_TIMEOUT_SHIFT);\r
431                 if (!NT_SUCCESS(status))\r
432                         goto end;\r
433                 break;
434 \r
435         default:\r
436                 status = STATUS_NOT_SUPPORTED;\r
437                 break;\r
438         }\r
439 end:\r
440         if (!requestPending)\r
441         {\r
442                 WdfRequestCompleteWithInformation(Request, status, sizeof(ULONG));\r
443         }\r
444 \r
445         return;\r