tps65217.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527
  1. /*++
  2. Copyright (c) 2015 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. tps65217.c
  5. Abstract:
  6. This module implements support for the TPS65217 Power Management IC.
  7. Author:
  8. Evan Green 8-Sep-2015
  9. Environment:
  10. Kernel
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include <minoca/kernel/driver.h>
  16. #include <minoca/spb/spb.h>
  17. #include <minoca/intrface/tps65217.h>
  18. #include "tps65217.h"
  19. //
  20. // ---------------------------------------------------------------- Definitions
  21. //
  22. #define TPS65217_ALLOCATION_TAG 0x35367054
  23. #define TPS65217_MAX_PACKET_SIZE 2
  24. #define TPS65217_DCDC_SETTINGS 64
  25. //
  26. // ------------------------------------------------------ Data Type Definitions
  27. //
  28. typedef enum _TPS65217_PASSWORD_LEVEL {
  29. Tps65217PasswordNone,
  30. Tps65217PasswordLevel1,
  31. Tps65217PasswordLevel2
  32. } TPS65217_PASSWORD_LEVEL, *PTPS65217_PASSWORD_LEVEL;
  33. /*++
  34. Structure Description:
  35. This structure defines the context for a TPS65217 PMIC.
  36. Members:
  37. OsDevice - Stores a pointer to the OS device object.
  38. InterruptLine - Stores the interrupt line that this controller's interrupt
  39. comes in on.
  40. InterruptVector - Stores the interrupt vector that this controller's
  41. interrupt comes in on.
  42. InterruptResourcesFound - Stores a boolean indicating whether or not the
  43. interrupt line and interrupt vector fields are valid.
  44. InterruptHandle - Stores a pointer to the handle received when the
  45. interrupt was connected.
  46. Lock - Stores a pointer to a lock serializing access to the controller.
  47. SpbResource - Stores a pointer to the Simple Peripheral Bus resource
  48. allocation used to connect to the controller.
  49. SpbSignedUp - Stores a boolean indicating whether or not interface
  50. notifications have been signed up for yet or not.
  51. SpbInterface - Stores a pointer to the Simple Peripheral Bus interface used
  52. to communicate with the device.
  53. SpbHandle - Stores the open handle to the Simple Peripheral Bus for this
  54. device.
  55. RequestBuffer - Stores a pointer to a buffer of size
  56. TPS65217_MAX_PACKET_SIZE used for request data.
  57. RequestIoBuffer - Stores a pointer to the I/O buffer around the request
  58. buffer.
  59. Interface - Stores the interface definition.
  60. --*/
  61. typedef struct _TPS65217_CONTROLLER {
  62. PDEVICE OsDevice;
  63. ULONGLONG InterruptLine;
  64. ULONGLONG InterruptVector;
  65. BOOL InterruptResourcesFound;
  66. HANDLE InterruptHandle;
  67. PQUEUED_LOCK Lock;
  68. PRESOURCE_ALLOCATION SpbResource;
  69. BOOL SpbSignedUp;
  70. PSPB_INTERFACE SpbInterface;
  71. SPB_HANDLE SpbHandle;
  72. PVOID RequestBuffer;
  73. PIO_BUFFER RequestIoBuffer;
  74. INTERFACE_TPS65217 Interface;
  75. } TPS65217_CONTROLLER, *PTPS65217_CONTROLLER;
  76. //
  77. // ----------------------------------------------- Internal Function Prototypes
  78. //
  79. KSTATUS
  80. Tps65217AddDevice (
  81. PVOID Driver,
  82. PSTR DeviceId,
  83. PSTR ClassId,
  84. PSTR CompatibleIds,
  85. PVOID DeviceToken
  86. );
  87. VOID
  88. Tps65217DispatchStateChange (
  89. PIRP Irp,
  90. PVOID DeviceContext,
  91. PVOID IrpContext
  92. );
  93. VOID
  94. Tps65217DispatchOpen (
  95. PIRP Irp,
  96. PVOID DeviceContext,
  97. PVOID IrpContext
  98. );
  99. VOID
  100. Tps65217DispatchClose (
  101. PIRP Irp,
  102. PVOID DeviceContext,
  103. PVOID IrpContext
  104. );
  105. VOID
  106. Tps65217DispatchIo (
  107. PIRP Irp,
  108. PVOID DeviceContext,
  109. PVOID IrpContext
  110. );
  111. VOID
  112. Tps65217DispatchSystemControl (
  113. PIRP Irp,
  114. PVOID DeviceContext,
  115. PVOID IrpContext
  116. );
  117. INTERRUPT_STATUS
  118. Tps65217InterruptServiceWorker (
  119. PVOID Context
  120. );
  121. KSTATUS
  122. Tps65217ProcessResourceRequirements (
  123. PIRP Irp
  124. );
  125. KSTATUS
  126. Tps65217StartDevice (
  127. PIRP Irp,
  128. PTPS65217_CONTROLLER Device
  129. );
  130. VOID
  131. Tps65217SpbInterfaceNotificationCallback (
  132. PVOID Context,
  133. PDEVICE Device,
  134. PVOID InterfaceBuffer,
  135. ULONG InterfaceBufferSize,
  136. BOOL Arrival
  137. );
  138. KSTATUS
  139. Tps65217Initialize (
  140. PTPS65217_CONTROLLER Controller
  141. );
  142. VOID
  143. Tps65217InterruptThread (
  144. PVOID Parameter
  145. );
  146. KSTATUS
  147. Tps65217InterfaceSetDcDcRegulator (
  148. PINTERFACE_TPS65217 Interface,
  149. TPS65217_DCDC_REGULATOR Regulator,
  150. ULONG Millivolts
  151. );
  152. KSTATUS
  153. Tps65217SetDcDcRegulator (
  154. PTPS65217_CONTROLLER Controller,
  155. TPS65217_REGISTER Register,
  156. ULONG Millivolts
  157. );
  158. KSTATUS
  159. Tps65217Write (
  160. PTPS65217_CONTROLLER Controller,
  161. TPS65217_REGISTER Register,
  162. UCHAR Data
  163. );
  164. KSTATUS
  165. Tps65217Read (
  166. PTPS65217_CONTROLLER Controller,
  167. TPS65217_REGISTER Register,
  168. PUCHAR Data
  169. );
  170. KSTATUS
  171. Tps65217AccessRegister (
  172. PTPS65217_CONTROLLER Controller,
  173. TPS65217_REGISTER Register,
  174. PUCHAR Data,
  175. BOOL Write
  176. );
  177. //
  178. // -------------------------------------------------------------------- Globals
  179. //
  180. //
  181. // Define the password levels for each register.
  182. //
  183. const TPS65217_PASSWORD_LEVEL Tps65217PasswordLevel[Tps65217RegisterCount] = {
  184. Tps65217PasswordNone,
  185. Tps65217PasswordNone,
  186. Tps65217PasswordNone,
  187. Tps65217PasswordNone,
  188. Tps65217PasswordNone,
  189. Tps65217PasswordNone,
  190. Tps65217PasswordNone,
  191. Tps65217PasswordNone,
  192. Tps65217PasswordNone,
  193. Tps65217PasswordNone,
  194. Tps65217PasswordNone,
  195. Tps65217PasswordNone,
  196. Tps65217PasswordNone,
  197. Tps65217PasswordLevel1,
  198. Tps65217PasswordLevel2,
  199. Tps65217PasswordLevel2,
  200. Tps65217PasswordLevel2,
  201. Tps65217PasswordLevel2,
  202. Tps65217PasswordLevel2,
  203. Tps65217PasswordLevel2,
  204. Tps65217PasswordLevel2,
  205. Tps65217PasswordLevel2,
  206. Tps65217PasswordLevel1,
  207. Tps65217PasswordNone,
  208. Tps65217PasswordLevel1,
  209. Tps65217PasswordLevel1,
  210. Tps65217PasswordLevel1,
  211. Tps65217PasswordLevel1,
  212. Tps65217PasswordLevel1,
  213. Tps65217PasswordLevel1,
  214. Tps65217PasswordLevel1,
  215. };
  216. //
  217. // Store the conversion from DCDC regulator values to millivolts.
  218. //
  219. const USHORT Tps65217DcDcMillivolts[TPS65217_DCDC_SETTINGS] = {
  220. 900,
  221. 925,
  222. 950,
  223. 975,
  224. 1000,
  225. 1025,
  226. 1050,
  227. 1075,
  228. 1100,
  229. 1125,
  230. 1150,
  231. 1175,
  232. 1200,
  233. 1225,
  234. 1250,
  235. 1275,
  236. 1300,
  237. 1325,
  238. 1350,
  239. 1375,
  240. 1400,
  241. 1425,
  242. 1450,
  243. 1475,
  244. 1500,
  245. 1550,
  246. 1600,
  247. 1650,
  248. 1700,
  249. 1750,
  250. 1800,
  251. 1850,
  252. 1900,
  253. 1950,
  254. 2000,
  255. 2050,
  256. 2100,
  257. 2150,
  258. 2200,
  259. 2250,
  260. 2300,
  261. 2350,
  262. 2400,
  263. 2450,
  264. 2500,
  265. 2550,
  266. 2600,
  267. 2650,
  268. 2700,
  269. 2750,
  270. 2800,
  271. 2850,
  272. 2900,
  273. 3000,
  274. 3100,
  275. 3200,
  276. 3300,
  277. 3300,
  278. 3300,
  279. 3300,
  280. 3300,
  281. 3300,
  282. 3300,
  283. 3300
  284. };
  285. PDRIVER Tps65217Driver;
  286. UUID Tps65217SpbInterfaceUuid = UUID_SPB_INTERFACE;
  287. UUID Tps65217InterfaceUuid = UUID_TPS65217_INTERFACE;
  288. INTERFACE_TPS65217 Tps65217InterfaceTemplate = {
  289. NULL,
  290. Tps65217InterfaceSetDcDcRegulator
  291. };
  292. //
  293. // ------------------------------------------------------------------ Functions
  294. //
  295. KSTATUS
  296. DriverEntry (
  297. PDRIVER Driver
  298. )
  299. /*++
  300. Routine Description:
  301. This routine is the entry point for the TPS65217. It registers its other
  302. dispatch functions, and performs driver-wide initialization.
  303. Arguments:
  304. Driver - Supplies a pointer to the driver object.
  305. Return Value:
  306. STATUS_SUCCESS on success.
  307. Failure code on error.
  308. --*/
  309. {
  310. DRIVER_FUNCTION_TABLE FunctionTable;
  311. KSTATUS Status;
  312. Tps65217Driver = Driver;
  313. RtlZeroMemory(&FunctionTable, sizeof(DRIVER_FUNCTION_TABLE));
  314. FunctionTable.Version = DRIVER_FUNCTION_TABLE_VERSION;
  315. FunctionTable.AddDevice = Tps65217AddDevice;
  316. FunctionTable.DispatchStateChange = Tps65217DispatchStateChange;
  317. FunctionTable.DispatchOpen = Tps65217DispatchOpen;
  318. FunctionTable.DispatchClose = Tps65217DispatchClose;
  319. FunctionTable.DispatchIo = Tps65217DispatchIo;
  320. FunctionTable.DispatchSystemControl = Tps65217DispatchSystemControl;
  321. Status = IoRegisterDriverFunctions(Driver, &FunctionTable);
  322. return Status;
  323. }
  324. KSTATUS
  325. Tps65217AddDevice (
  326. PVOID Driver,
  327. PSTR DeviceId,
  328. PSTR ClassId,
  329. PSTR CompatibleIds,
  330. PVOID DeviceToken
  331. )
  332. /*++
  333. Routine Description:
  334. This routine is called when a device is detected for which this driver
  335. acts as the function driver. The driver will attach itself to the stack.
  336. Arguments:
  337. Driver - Supplies a pointer to the driver being called.
  338. DeviceId - Supplies a pointer to a string with the device ID.
  339. ClassId - Supplies a pointer to a string containing the device's class ID.
  340. CompatibleIds - Supplies a pointer to a string containing device IDs
  341. that would be compatible with this device.
  342. DeviceToken - Supplies an opaque token that the driver can use to identify
  343. the device in the system. This token should be used when attaching to
  344. the stack.
  345. Return Value:
  346. STATUS_SUCCESS on success.
  347. Failure code if the driver was unsuccessful in attaching itself.
  348. --*/
  349. {
  350. UINTN AllocationSize;
  351. PTPS65217_CONTROLLER Controller;
  352. KSTATUS Status;
  353. AllocationSize = sizeof(TPS65217_CONTROLLER) + TPS65217_MAX_PACKET_SIZE;
  354. Controller = MmAllocatePagedPool(AllocationSize, TPS65217_ALLOCATION_TAG);
  355. if (Controller == NULL) {
  356. return STATUS_INSUFFICIENT_RESOURCES;
  357. }
  358. RtlZeroMemory(Controller, AllocationSize);
  359. Controller->OsDevice = DeviceToken;
  360. Controller->InterruptHandle = INVALID_HANDLE;
  361. Controller->RequestBuffer = (PVOID)(Controller + 1);
  362. RtlCopyMemory(&(Controller->Interface),
  363. &Tps65217InterfaceTemplate,
  364. sizeof(INTERFACE_TPS65217));
  365. Status = MmCreateIoBuffer(Controller->RequestBuffer,
  366. TPS65217_MAX_PACKET_SIZE,
  367. IO_BUFFER_FLAG_KERNEL_MODE_DATA,
  368. &(Controller->RequestIoBuffer));
  369. if (!KSUCCESS(Status)) {
  370. Status = STATUS_INSUFFICIENT_RESOURCES;
  371. goto AddDeviceEnd;
  372. }
  373. Controller->Lock = KeCreateQueuedLock();
  374. if (Controller->Lock == NULL) {
  375. Status = STATUS_INSUFFICIENT_RESOURCES;
  376. goto AddDeviceEnd;
  377. }
  378. Status = IoAttachDriverToDevice(Driver, DeviceToken, Controller);
  379. AddDeviceEnd:
  380. if (!KSUCCESS(Status)) {
  381. if (Controller != NULL) {
  382. if (Controller->RequestIoBuffer != NULL) {
  383. MmFreeIoBuffer(Controller->RequestIoBuffer);
  384. }
  385. if (Controller->Lock != NULL) {
  386. KeDestroyQueuedLock(Controller->Lock);
  387. }
  388. MmFreePagedPool(Controller);
  389. }
  390. }
  391. return Status;
  392. }
  393. VOID
  394. Tps65217DispatchStateChange (
  395. PIRP Irp,
  396. PVOID DeviceContext,
  397. PVOID IrpContext
  398. )
  399. /*++
  400. Routine Description:
  401. This routine handles State Change IRPs.
  402. Arguments:
  403. Irp - Supplies a pointer to the I/O request packet.
  404. DeviceContext - Supplies the context pointer supplied by the driver when it
  405. attached itself to the driver stack. Presumably this pointer contains
  406. driver-specific device context.
  407. IrpContext - Supplies the context pointer supplied by the driver when
  408. the IRP was created.
  409. Return Value:
  410. None.
  411. --*/
  412. {
  413. KSTATUS Status;
  414. ASSERT(Irp->MajorCode == IrpMajorStateChange);
  415. if (Irp->Direction == IrpUp) {
  416. switch (Irp->MinorCode) {
  417. case IrpMinorQueryResources:
  418. Status = Tps65217ProcessResourceRequirements(Irp);
  419. if (!KSUCCESS(Status)) {
  420. IoCompleteIrp(Tps65217Driver, Irp, Status);
  421. }
  422. break;
  423. case IrpMinorStartDevice:
  424. Status = Tps65217StartDevice(Irp, DeviceContext);
  425. if (!KSUCCESS(Status)) {
  426. IoCompleteIrp(Tps65217Driver, Irp, Status);
  427. }
  428. break;
  429. default:
  430. break;
  431. }
  432. }
  433. return;
  434. }
  435. VOID
  436. Tps65217DispatchOpen (
  437. PIRP Irp,
  438. PVOID DeviceContext,
  439. PVOID IrpContext
  440. )
  441. /*++
  442. Routine Description:
  443. This routine handles Open IRPs.
  444. Arguments:
  445. Irp - Supplies a pointer to the I/O request packet.
  446. DeviceContext - Supplies the context pointer supplied by the driver when it
  447. attached itself to the driver stack. Presumably this pointer contains
  448. driver-specific device context.
  449. IrpContext - Supplies the context pointer supplied by the driver when
  450. the IRP was created.
  451. Return Value:
  452. None.
  453. --*/
  454. {
  455. return;
  456. }
  457. VOID
  458. Tps65217DispatchClose (
  459. PIRP Irp,
  460. PVOID DeviceContext,
  461. PVOID IrpContext
  462. )
  463. /*++
  464. Routine Description:
  465. This routine handles Close IRPs.
  466. Arguments:
  467. Irp - Supplies a pointer to the I/O request packet.
  468. DeviceContext - Supplies the context pointer supplied by the driver when it
  469. attached itself to the driver stack. Presumably this pointer contains
  470. driver-specific device context.
  471. IrpContext - Supplies the context pointer supplied by the driver when
  472. the IRP was created.
  473. Return Value:
  474. None.
  475. --*/
  476. {
  477. return;
  478. }
  479. VOID
  480. Tps65217DispatchIo (
  481. PIRP Irp,
  482. PVOID DeviceContext,
  483. PVOID IrpContext
  484. )
  485. /*++
  486. Routine Description:
  487. This routine handles I/O IRPs.
  488. Arguments:
  489. Irp - Supplies a pointer to the I/O request packet.
  490. DeviceContext - Supplies the context pointer supplied by the driver when it
  491. attached itself to the driver stack. Presumably this pointer contains
  492. driver-specific device context.
  493. IrpContext - Supplies the context pointer supplied by the driver when
  494. the IRP was created.
  495. Return Value:
  496. None.
  497. --*/
  498. {
  499. return;
  500. }
  501. VOID
  502. Tps65217DispatchSystemControl (
  503. PIRP Irp,
  504. PVOID DeviceContext,
  505. PVOID IrpContext
  506. )
  507. /*++
  508. Routine Description:
  509. This routine handles System Control IRPs.
  510. Arguments:
  511. Irp - Supplies a pointer to the I/O request packet.
  512. DeviceContext - Supplies the context pointer supplied by the driver when it
  513. attached itself to the driver stack. Presumably this pointer contains
  514. driver-specific device context.
  515. IrpContext - Supplies the context pointer supplied by the driver when
  516. the IRP was created.
  517. Return Value:
  518. None.
  519. --*/
  520. {
  521. ASSERT(Irp->MajorCode == IrpMajorSystemControl);
  522. //
  523. // Do no processing on any IRPs. Let them flow.
  524. //
  525. return;
  526. }
  527. INTERRUPT_STATUS
  528. Tps65217InterruptServiceWorker (
  529. PVOID Context
  530. )
  531. /*++
  532. Routine Description:
  533. This routine represents the low level interrupt service routine for the
  534. TPS65217.
  535. Arguments:
  536. Context - Supplies the context supplied when this interrupt was initially
  537. connected.
  538. Return Value:
  539. Returns an interrupt status indicating if this ISR is claiming the
  540. interrupt, not claiming the interrupt, or needs the interrupt to be
  541. masked temporarily.
  542. --*/
  543. {
  544. KSTATUS Status;
  545. THREAD_CREATION_PARAMETERS ThreadParameters;
  546. RtlZeroMemory(&ThreadParameters, sizeof(THREAD_CREATION_PARAMETERS));
  547. ThreadParameters.ThreadRoutine = Tps65217InterruptThread;
  548. ThreadParameters.Parameter = Context;
  549. Status = PsCreateThread(&ThreadParameters);
  550. if (!KSUCCESS(Status)) {
  551. return InterruptStatusNotClaimed;
  552. }
  553. return InterruptStatusDefer;
  554. }
  555. //
  556. // --------------------------------------------------------- Internal Functions
  557. //
  558. KSTATUS
  559. Tps65217ProcessResourceRequirements (
  560. PIRP Irp
  561. )
  562. /*++
  563. Routine Description:
  564. This routine filters through the resource requirements presented by the
  565. bus for a TPS65217. It adds an interrupt vector requirement for any
  566. interrupt line requested.
  567. Arguments:
  568. Irp - Supplies a pointer to the I/O request packet.
  569. Return Value:
  570. Status code.
  571. --*/
  572. {
  573. PRESOURCE_CONFIGURATION_LIST Requirements;
  574. KSTATUS Status;
  575. RESOURCE_REQUIREMENT VectorRequirement;
  576. ASSERT((Irp->MajorCode == IrpMajorStateChange) &&
  577. (Irp->MinorCode == IrpMinorQueryResources));
  578. //
  579. // Initialize a nice interrupt vector requirement in preparation.
  580. //
  581. RtlZeroMemory(&VectorRequirement, sizeof(RESOURCE_REQUIREMENT));
  582. VectorRequirement.Type = ResourceTypeInterruptVector;
  583. VectorRequirement.Minimum = 0;
  584. VectorRequirement.Maximum = -1;
  585. VectorRequirement.Length = 1;
  586. //
  587. // Loop through all configuration lists, creating a vector for each line.
  588. //
  589. Requirements = Irp->U.QueryResources.ResourceRequirements;
  590. Status = IoCreateAndAddInterruptVectorsForLines(Requirements,
  591. &VectorRequirement);
  592. if (!KSUCCESS(Status)) {
  593. goto ProcessResourceRequirementsEnd;
  594. }
  595. ProcessResourceRequirementsEnd:
  596. return Status;
  597. }
  598. KSTATUS
  599. Tps65217StartDevice (
  600. PIRP Irp,
  601. PTPS65217_CONTROLLER Device
  602. )
  603. /*++
  604. Routine Description:
  605. This routine starts the TPS65217 PMIC device.
  606. Arguments:
  607. Irp - Supplies a pointer to the start IRP.
  608. Device - Supplies a pointer to the device information.
  609. Return Value:
  610. Status code.
  611. --*/
  612. {
  613. PRESOURCE_ALLOCATION Allocation;
  614. PRESOURCE_ALLOCATION_LIST AllocationList;
  615. IO_CONNECT_INTERRUPT_PARAMETERS Connect;
  616. PRESOURCE_ALLOCATION LineAllocation;
  617. KSTATUS Status;
  618. //
  619. // Loop through the allocated resources to get the controller base and the
  620. // interrupt.
  621. //
  622. ASSERT(Device->InterruptHandle == INVALID_HANDLE);
  623. Device->InterruptResourcesFound = FALSE;
  624. AllocationList = Irp->U.StartDevice.ProcessorLocalResources;
  625. Allocation = IoGetNextResourceAllocation(AllocationList, NULL);
  626. while (Allocation != NULL) {
  627. //
  628. // If the resource is an interrupt vector, then it should have an
  629. // owning interrupt line allocation.
  630. //
  631. if (Allocation->Type == ResourceTypeInterruptVector) {
  632. LineAllocation = Allocation->OwningAllocation;
  633. if (Device->InterruptResourcesFound == FALSE) {
  634. ASSERT(Allocation->OwningAllocation != NULL);
  635. //
  636. // Save the line and vector number.
  637. //
  638. Device->InterruptLine = LineAllocation->Allocation;
  639. Device->InterruptVector = Allocation->Allocation;
  640. Device->InterruptResourcesFound = TRUE;
  641. } else {
  642. ASSERT((Device->InterruptLine == LineAllocation->Allocation) &&
  643. (Device->InterruptVector == Allocation->Allocation));
  644. }
  645. } else if (Allocation->Type == ResourceTypeSimpleBus) {
  646. if (Device->SpbResource == NULL) {
  647. Device->SpbResource = Allocation;
  648. }
  649. }
  650. //
  651. // Get the next allocation in the list.
  652. //
  653. Allocation = IoGetNextResourceAllocation(AllocationList, Allocation);
  654. }
  655. if (Device->SpbResource == NULL) {
  656. Status = STATUS_NOT_READY;
  657. goto StartDeviceEnd;
  658. }
  659. //
  660. // Sign up for interface notifications on the Simple Bus device to get
  661. // access to the simple bus interface. This should call back immediately.
  662. //
  663. if (Device->SpbSignedUp == FALSE) {
  664. Status = IoRegisterForInterfaceNotifications(
  665. &Tps65217SpbInterfaceUuid,
  666. Tps65217SpbInterfaceNotificationCallback,
  667. Device->SpbResource->Provider,
  668. Device,
  669. TRUE);
  670. if (!KSUCCESS(Status)) {
  671. goto StartDeviceEnd;
  672. }
  673. Device->SpbSignedUp = TRUE;
  674. }
  675. //
  676. // The device cannot start up if there is no bus interface to talk over.
  677. //
  678. if (Device->SpbInterface == NULL) {
  679. Status = STATUS_NO_INTERFACE;
  680. goto StartDeviceEnd;
  681. }
  682. //
  683. // Try to open up communications over the simple bus.
  684. //
  685. if (Device->SpbHandle == NULL) {
  686. ASSERT(Device->SpbResource->DataSize >= sizeof(RESOURCE_SPB_DATA));
  687. KeAcquireQueuedLock(Device->Lock);
  688. Status = Device->SpbInterface->Open(Device->SpbInterface,
  689. Device->SpbResource->Data,
  690. &(Device->SpbHandle));
  691. KeReleaseQueuedLock(Device->Lock);
  692. if (!KSUCCESS(Status)) {
  693. RtlDebugPrint("TPS65217: Open SPB Failed: %x\n", Status);
  694. goto StartDeviceEnd;
  695. }
  696. }
  697. Status = Tps65217Initialize(Device);
  698. if (!KSUCCESS(Status)) {
  699. goto StartDeviceEnd;
  700. }
  701. //
  702. // Connect the interrupt.
  703. //
  704. if ((Device->InterruptHandle == INVALID_HANDLE) &&
  705. (Device->InterruptResourcesFound != FALSE)) {
  706. RtlZeroMemory(&Connect, sizeof(IO_CONNECT_INTERRUPT_PARAMETERS));
  707. Connect.Version = IO_CONNECT_INTERRUPT_PARAMETERS_VERSION;
  708. Connect.Device = Irp->Device;
  709. Connect.LineNumber = Device->InterruptLine;
  710. Connect.Vector = Device->InterruptVector;
  711. Connect.LowLevelServiceRoutine = Tps65217InterruptServiceWorker;
  712. Connect.Context = Device;
  713. Connect.Interrupt = &(Device->InterruptHandle);
  714. Status = IoConnectInterrupt(&Connect);
  715. if (!KSUCCESS(Status)) {
  716. return Status;
  717. }
  718. }
  719. //
  720. // Publish the interface.
  721. //
  722. if (Device->Interface.Context == NULL) {
  723. Device->Interface.Context = Device;
  724. Status = IoCreateInterface(&Tps65217InterfaceUuid,
  725. Device->OsDevice,
  726. &(Device->Interface),
  727. sizeof(Device->Interface));
  728. if (!KSUCCESS(Status)) {
  729. Device->Interface.Context = NULL;
  730. goto StartDeviceEnd;
  731. }
  732. }
  733. StartDeviceEnd:
  734. return Status;
  735. }
  736. VOID
  737. Tps65217SpbInterfaceNotificationCallback (
  738. PVOID Context,
  739. PDEVICE Device,
  740. PVOID InterfaceBuffer,
  741. ULONG InterfaceBufferSize,
  742. BOOL Arrival
  743. )
  744. /*++
  745. Routine Description:
  746. This routine is called to notify listeners that an interface has arrived
  747. or departed.
  748. Arguments:
  749. Context - Supplies the caller's context pointer, supplied when the caller
  750. requested interface notifications.
  751. Device - Supplies a pointer to the device exposing or deleting the
  752. interface.
  753. InterfaceBuffer - Supplies a pointer to the interface buffer of the
  754. interface.
  755. InterfaceBufferSize - Supplies the buffer size.
  756. Arrival - Supplies TRUE if a new interface is arriving, or FALSE if an
  757. interface is departing.
  758. Return Value:
  759. None.
  760. --*/
  761. {
  762. PTPS65217_CONTROLLER Controller;
  763. PSPB_INTERFACE Interface;
  764. KSTATUS Status;
  765. Controller = Context;
  766. KeAcquireQueuedLock(Controller->Lock);
  767. //
  768. // If the interface is arriving, store a pointer to it.
  769. //
  770. if (Arrival != FALSE) {
  771. Interface = InterfaceBuffer;
  772. if (InterfaceBufferSize < sizeof(SPB_INTERFACE)) {
  773. ASSERT(FALSE);
  774. return;
  775. }
  776. ASSERT(Controller->SpbInterface == NULL);
  777. Controller->SpbInterface = Interface;
  778. ASSERT(Controller->SpbHandle == NULL);
  779. //
  780. // If the interface is disappearing, close the handle.
  781. //
  782. } else {
  783. //
  784. // First close the published interface.
  785. //
  786. if (Controller->Interface.Context != NULL) {
  787. ASSERT(Controller->Interface.Context == Controller);
  788. Status = IoDestroyInterface(&Tps65217InterfaceUuid,
  789. Controller->OsDevice,
  790. &(Controller->Interface));
  791. ASSERT(KSUCCESS(Status));
  792. Controller->Interface.Context = NULL;
  793. }
  794. Interface = Controller->SpbInterface;
  795. if (Controller->SpbHandle != NULL) {
  796. Interface->Close(Interface, Controller->SpbHandle);
  797. Controller->SpbHandle = NULL;
  798. }
  799. Controller->SpbInterface = NULL;
  800. }
  801. KeReleaseQueuedLock(Controller->Lock);
  802. return;
  803. }
  804. KSTATUS
  805. Tps65217Initialize (
  806. PTPS65217_CONTROLLER Controller
  807. )
  808. /*++
  809. Routine Description:
  810. This routine initializes the TPS65217 PMIC. It reads the chip revision.
  811. Arguments:
  812. Controller - Supplies a pointer to the controller.
  813. Return Value:
  814. Status code.
  815. --*/
  816. {
  817. UCHAR ChipId;
  818. UCHAR ChipId2;
  819. ULONG LoopIndex;
  820. KSTATUS Status;
  821. KeAcquireQueuedLock(Controller->Lock);
  822. Status = Tps65217Read(Controller, Tps65217ChipId, &ChipId);
  823. if (!KSUCCESS(Status)) {
  824. goto InitializeEnd;
  825. }
  826. if ((ChipId == 0) || (ChipId == 0xFF)) {
  827. Status = STATUS_DEVICE_IO_ERROR;
  828. goto InitializeEnd;
  829. }
  830. for (LoopIndex = 0; LoopIndex < 20; LoopIndex += 1) {
  831. Status = Tps65217Read(Controller, Tps65217ChipId, &ChipId2);
  832. if (!KSUCCESS(Status)) {
  833. RtlDebugPrint("Failed on loop %d\n", LoopIndex);
  834. ASSERT(FALSE);
  835. goto InitializeEnd;
  836. }
  837. if (ChipId2 != ChipId) {
  838. RtlDebugPrint("Mismatch (%d) %x %x\n", LoopIndex, ChipId, ChipId2);
  839. }
  840. }
  841. InitializeEnd:
  842. KeReleaseQueuedLock(Controller->Lock);
  843. return Status;
  844. }
  845. VOID
  846. Tps65217InterruptThread (
  847. PVOID Parameter
  848. )
  849. /*++
  850. Routine Description:
  851. This routine is the entry point for a new thread that is spawned each time
  852. the TPS65217 interrupt fires.
  853. Arguments:
  854. Parameter - Supplies a context pointer, which in this case points to the
  855. controller.
  856. Return Value:
  857. None.
  858. --*/
  859. {
  860. PTPS65217_CONTROLLER Controller;
  861. UCHAR InterruptRegister;
  862. INTERRUPT_STATUS InterruptStatus;
  863. KSTATUS Status;
  864. InterruptStatus = InterruptStatusNotClaimed;
  865. Controller = Parameter;
  866. Status = Tps65217Read(Controller, Tps65217Interrupt, &InterruptRegister);
  867. if (!KSUCCESS(Status)) {
  868. goto InterruptThreadEnd;
  869. }
  870. RtlDebugPrint("TPS65217 Interrupt %x\n", InterruptRegister);
  871. if ((InterruptRegister & TPS65217_INTERRUPT_STATUS_MASK) != 0) {
  872. InterruptStatus = InterruptStatusClaimed;
  873. }
  874. InterruptThreadEnd:
  875. HlContinueInterrupt(Controller->InterruptHandle, InterruptStatus);
  876. return;
  877. }
  878. KSTATUS
  879. Tps65217InterfaceSetDcDcRegulator (
  880. PINTERFACE_TPS65217 Interface,
  881. TPS65217_DCDC_REGULATOR Regulator,
  882. ULONG Millivolts
  883. )
  884. /*++
  885. Routine Description:
  886. This routine sets a TPS65217 DC-DC regulator voltage to the given value.
  887. Arguments:
  888. Interface - Supplies a pointer to the interface instance.
  889. Regulator - Supplies the regulator number to change.
  890. Millivolts - Supplies the millivolt value to change to.
  891. Return Value:
  892. Status code.
  893. --*/
  894. {
  895. PTPS65217_CONTROLLER Controller;
  896. TPS65217_REGISTER Register;
  897. KSTATUS Status;
  898. Controller = Interface->Context;
  899. switch (Regulator) {
  900. case Tps65217DcDc1:
  901. Register = Tps65217DcDc1Voltage;
  902. break;
  903. case Tps65217DcDc2:
  904. Register = Tps65217DcDc2Voltage;
  905. break;
  906. case Tps65217DcDc3:
  907. Register = Tps65217DcDc3Voltage;
  908. break;
  909. default:
  910. return STATUS_INVALID_PARAMETER;
  911. }
  912. KeAcquireQueuedLock(Controller->Lock);
  913. Status = Tps65217SetDcDcRegulator(Controller, Register, Millivolts);
  914. KeReleaseQueuedLock(Controller->Lock);
  915. return Status;
  916. }
  917. KSTATUS
  918. Tps65217SetDcDcRegulator (
  919. PTPS65217_CONTROLLER Controller,
  920. TPS65217_REGISTER Register,
  921. ULONG Millivolts
  922. )
  923. /*++
  924. Routine Description:
  925. This routine sets a TPS65217 DC-DC regulator voltage to the given value.
  926. This routine assumes the controller lock is already held.
  927. Arguments:
  928. Controller - Supplies a pointer to the controller.
  929. Register - Supplies the DC-DC regulator register to set.
  930. Millivolts - Supplies the millivolt value to change to.
  931. Return Value:
  932. STATUS_SUCCESS on success.
  933. STATUS_NOT_SUPPORTED if the given voltage value cannot be achieved.
  934. Other errors on I/O failure.
  935. --*/
  936. {
  937. UCHAR Control;
  938. ULONG Index;
  939. KSTATUS Status;
  940. UCHAR Value;
  941. //
  942. // Convert from millivolts to a register value.
  943. //
  944. Value = 0;
  945. for (Index = 0; Index < TPS65217_DCDC_SETTINGS; Index += 1) {
  946. if (Tps65217DcDcMillivolts[Index] == Millivolts) {
  947. Value = Index;
  948. break;
  949. }
  950. }
  951. if (Index == TPS65217_DCDC_SETTINGS) {
  952. return STATUS_NOT_SUPPORTED;
  953. }
  954. Status = Tps65217Write(Controller, Register, Value);
  955. if (!KSUCCESS(Status)) {
  956. return Status;
  957. }
  958. //
  959. // Set the GO bit to enact the change.
  960. //
  961. Status = Tps65217Read(Controller, Tps65217SlewControl, &Control);
  962. if (!KSUCCESS(Status)) {
  963. return Status;
  964. }
  965. Control |= TPS65217_SLEW_CONTROL_DCDC_GO;
  966. Status = Tps65217Write(Controller, Tps65217SlewControl, Control);
  967. if (!KSUCCESS(Status)) {
  968. return Status;
  969. }
  970. return Status;
  971. }
  972. KSTATUS
  973. Tps65217Write (
  974. PTPS65217_CONTROLLER Controller,
  975. TPS65217_REGISTER Register,
  976. UCHAR Data
  977. )
  978. /*++
  979. Routine Description:
  980. This routine reads a TPS65217 register over I2C. This routine takes care of
  981. the password protocol.
  982. Arguments:
  983. Controller - Supplies a pointer to the controller.
  984. Register - Supplies the register to write.
  985. Data - Supplies a pointer where the register contents will be returned on
  986. success.
  987. Return Value:
  988. Status code.
  989. --*/
  990. {
  991. ULONG LoopIndex;
  992. ULONG Loops;
  993. UCHAR Password;
  994. KSTATUS Status;
  995. Loops = 0;
  996. if (Register > Tps65217RegisterCount) {
  997. return STATUS_INVALID_PARAMETER;
  998. }
  999. Status = STATUS_SUCCESS;
  1000. switch (Tps65217PasswordLevel[Register]) {
  1001. case Tps65217PasswordNone:
  1002. Status = Tps65217AccessRegister(Controller, Register, &Data, TRUE);
  1003. break;
  1004. case Tps65217PasswordLevel1:
  1005. Loops = 1;
  1006. break;
  1007. case Tps65217PasswordLevel2:
  1008. Loops = 2;
  1009. break;
  1010. default:
  1011. ASSERT(FALSE);
  1012. Status = STATUS_INVALID_PARAMETER;
  1013. break;
  1014. }
  1015. //
  1016. // Write the password, then the data. For level 1 registers this only needs
  1017. // to be done once, but for level 2 registers this needs to be done twice.
  1018. //
  1019. for (LoopIndex = 0; LoopIndex < Loops; LoopIndex += 1) {
  1020. Password = TPS65217_PASSWORD_UNLOCK ^ Register;
  1021. Status = Tps65217AccessRegister(Controller,
  1022. Tps65217Password,
  1023. &Password,
  1024. TRUE);
  1025. if (!KSUCCESS(Status)) {
  1026. return Status;
  1027. }
  1028. Status = Tps65217AccessRegister(Controller, Register, &Data, TRUE);
  1029. if (!KSUCCESS(Status)) {
  1030. return Status;
  1031. }
  1032. }
  1033. return Status;
  1034. }
  1035. KSTATUS
  1036. Tps65217Read (
  1037. PTPS65217_CONTROLLER Controller,
  1038. TPS65217_REGISTER Register,
  1039. PUCHAR Data
  1040. )
  1041. /*++
  1042. Routine Description:
  1043. This routine reads a TPS65217 register over I2C.
  1044. Arguments:
  1045. Controller - Supplies a pointer to the controller.
  1046. Register - Supplies the register to read.
  1047. Data - Supplies a pointer where the register contents will be returned on
  1048. success.
  1049. Return Value:
  1050. Status code.
  1051. --*/
  1052. {
  1053. return Tps65217AccessRegister(Controller, Register, Data, FALSE);
  1054. }
  1055. KSTATUS
  1056. Tps65217AccessRegister (
  1057. PTPS65217_CONTROLLER Controller,
  1058. TPS65217_REGISTER Register,
  1059. PUCHAR Data,
  1060. BOOL Write
  1061. )
  1062. /*++
  1063. Routine Description:
  1064. This routine performs an I2C bus access to get or set a single register.
  1065. Note that this routine alone is not sufficient to write to many TPS
  1066. registers, due to the password mechanism.
  1067. Arguments:
  1068. Controller - Supplies a pointer to the controller.
  1069. Register - Supplies the register to read or write.
  1070. Data - Supplies a pointer to the register content (either the value to
  1071. write or where the read data will be returned).
  1072. Write - Supplies a boolean indicating whether to read the register (FALSE)
  1073. or write the register.
  1074. Return Value:
  1075. Status code.
  1076. --*/
  1077. {
  1078. PUCHAR Buffer;
  1079. PSPB_INTERFACE Interface;
  1080. KSTATUS Status;
  1081. SPB_TRANSFER Transfer[2];
  1082. SPB_TRANSFER_SET TransferSet;
  1083. Buffer = Controller->RequestBuffer;
  1084. Buffer[0] = Register;
  1085. RtlZeroMemory(Transfer, sizeof(Transfer));
  1086. Transfer[0].Direction = SpbTransferDirectionOut;
  1087. Transfer[0].IoBuffer = Controller->RequestIoBuffer;
  1088. Transfer[0].Size = 1;
  1089. Transfer[1].Direction = SpbTransferDirectionIn;
  1090. if (Write != FALSE) {
  1091. Transfer[1].Direction = SpbTransferDirectionOut;
  1092. Buffer[1] = *Data;
  1093. }
  1094. Transfer[1].IoBuffer = Controller->RequestIoBuffer;
  1095. Transfer[1].Offset = 1;
  1096. Transfer[1].Size = 1;
  1097. RtlZeroMemory(&TransferSet, sizeof(TransferSet));
  1098. INITIALIZE_LIST_HEAD(&(TransferSet.TransferList));
  1099. INSERT_BEFORE(&(Transfer[0].ListEntry), &(TransferSet.TransferList));
  1100. INSERT_BEFORE(&(Transfer[1].ListEntry), &(TransferSet.TransferList));
  1101. Interface = Controller->SpbInterface;
  1102. Status = Interface->ExecuteTransferSet(Controller->SpbHandle, &TransferSet);
  1103. if (!KSUCCESS(Status)) {
  1104. return Status;
  1105. }
  1106. if (Write == FALSE) {
  1107. *Data = Buffer[1];
  1108. }
  1109. return Status;
  1110. }