1 /* 2 * Copyright (c) 2012 Corey Tabaka 3 * 4 * Use of this source code is governed by a MIT-style 5 * license that can be found in the LICENSE file or at 6 * https://opensource.org/licenses/MIT 7 */ 8 #pragma once 9 10 #include <sys/types.h> 11 #include <lk/list.h> // for containerof 12 #include <lk/compiler.h> 13 14 __BEGIN_CDECLS 15 16 struct driver; 17 18 /* 19 * Contains the data pertaining to an instance of a device. More than one 20 * instance may exist for a given driver type (i.e. uart0, uart1, etc..). 21 */ 22 struct device { 23 const char *name; 24 const struct driver *driver; 25 26 uint32_t flags; 27 28 /* instance specific config data populated at instantiation */ 29 const void *config; 30 31 /* instance specific data populated by the driver at init */ 32 void *state; 33 34 // TODO: add generic state, such as suspend/resume state, etc... 35 enum { 36 DEVICE_UNINITIALIZED, 37 DEVICE_INITIALIZED, 38 DEVICE_INITIALIZED_FAILED, 39 } device_state; 40 }; 41 42 /* set this flag to auto initialize the device when device_init_all is called */ 43 #define DEVICE_FLAG_AUTOINIT 0x1 44 45 /* device class, mainly used as a unique magic pointer to validate ops */ 46 struct device_class { 47 const char *name; 48 }; 49 50 /* standard driver ops; extensions should contain this ops structure */ 51 struct driver_ops { 52 const struct device_class *device_class; 53 54 status_t (*init)(struct device *dev); 55 status_t (*fini)(struct device *dev); 56 57 status_t (*suspend)(struct device *dev); 58 status_t (*resume)(struct device *dev); 59 }; 60 61 /* describes a driver, one per driver type */ 62 struct driver { 63 const char *type; 64 const struct driver_ops *ops; 65 }; 66 67 /* macro-expanding concat */ 68 #define concat(a, b) __ex_concat(a, b) 69 #define __ex_concat(a, b) a ## b 70 71 #define DRIVER_EXPORT(type_, ops_) \ 72 const struct driver concat(__driver_, type_) \ 73 __ALIGNED(sizeof(void *)) __SECTION("drivers") = { \ 74 .type = #type_, \ 75 .ops = ops_, \ 76 } 77 78 #define DEVICE_INSTANCE(type_, name_, config_, flags_) \ 79 extern const struct driver concat(__driver_, type_); \ 80 struct device concat(__device_, concat(type_, concat(_, name_))) \ 81 __ALIGNED(sizeof(void *)) __SECTION("devices") = { \ 82 .name = #name_, \ 83 .driver = &concat(__driver_, type_), \ 84 .flags = flags_, \ 85 .config = config_, \ 86 .state = NULL, \ 87 .device_state = DEVICE_UNINITIALIZED, \ 88 } 89 90 /* 91 * returns the driver specific ops pointer given the device instance, specific 92 * ops type, and generic ops member name within the specific ops structure. 93 */ 94 #define device_get_driver_ops(dev, type, member) ({ \ 95 type *__ops = NULL; \ 96 if (dev && dev->driver && dev->driver->ops) \ 97 __ops = containerof(dev->driver->ops, type, member); \ 98 __ops; \ 99 }) 100 101 #define device_get_by_name(type_, name_) ({ \ 102 extern struct device concat(__device_, concat(type_, concat(_, name_))); \ 103 &concat(__device_, concat(type_, concat(_, name_))); \ 104 }) 105 106 /* initialize all static devices with AUTOINIT flag set */ 107 status_t device_init_all(void); 108 109 status_t device_fini_all(void); 110 111 status_t device_init(struct device *dev); 112 status_t device_fini(struct device *dev); 113 114 status_t device_suspend(struct device *dev); 115 status_t device_resume(struct device *dev); 116 117 __END_CDECLS 118 119