2017年9月30日 星期六

platform_driver_register vs platform_device_register



//      kernel/include/linux/platform_device.h
struct platform_device {
const char *name;
int id;
bool id_auto;
struct device dev;
u32 num_resources;
struct resource *resource;

const struct platform_device_id *id_entry;
char *driver_override; /* Driver name to force a match */

/* MFD cell pointer */
struct mfd_cell *mfd_cell;

/* arch specific additions */
struct pdev_archdata archdata;
};

struct platform_driver {
int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
void (*shutdown)(struct platform_device *);
int (*suspend)(struct platform_device *, pm_message_t state);
int (*resume)(struct platform_device *);
struct device_driver driver;
const struct platform_device_id *id_table;
bool prevent_deferred_probe;
};


//      kernel/include/linux/platform_device.h
struct device_driver {
const char *name;
struct bus_type *bus;

struct module *owner;
const char *mod_name; /* used for built-in modules */

bool suppress_bind_attrs; /* disables bind/unbind via sysfs */
enum probe_type probe_type;

const struct of_device_id *of_match_table;
const struct acpi_device_id *acpi_match_table;

int (*probe) (struct device *dev);
int (*remove) (struct device *dev);
void (*shutdown) (struct device *dev);
int (*suspend) (struct device *dev, pm_message_t state);
int (*resume) (struct device *dev);
const struct attribute_group **groups;

const struct dev_pm_ops *pm;

struct driver_private *p;
};

常見的順序是先 platform_device_register,  然後,  platform_device_register

從網路上找到關於兩者的關係:

A. platform_device_register()
|
|
---------------------------------------------------------------------------------------------------------
bus type (Platform, I2C, SPI) 在bus driver中會作match()和呼叫driver probe()的動作,若有match的話
---------------------------------------------------------------------------------------------------------
|
|

B. platform_driver_register()
這邊分成兩個部分解釋:
1. 當device透過platform_device_register()時,會透過.match提供的API在bus上找尋name相同的driver是否已經被掛載了,若成立,則會call bus或driver所提供的probe函式來做driver的初始化動作。若不成立,則只是將該device掛到bus上就return。

2. 相同的,當driver透過platform_driver_register()註冊時,也是利用.match的方式在bus上尋找name相同的device是否已經掛接在bus上,若是,則啟動probe的函式完成driver的初始化。若否,則將driver掛接在bus上就return。

綜合以上,可以得知device和driver的掛接沒有誰先誰後的副作用,唯一的先決條件就是bus driver已經被註冊好。故platform bus是第一個要備系統給註冊起來,接著的device和driver就是透過platform_device_register()和platform_driver_register()將三者牽上關係。

//----------------------------------------------------------------------------------------

platform_driver_register()與platform_device_register() 

設備與驅動的兩種綁定方式:在設備註冊時進行綁定及在驅動註冊時進行綁定。以一個USB設備為例,有兩種情形:
(1)先插上USB設備並掛到總線(bus)中,然後在安裝USB驅動程序過程中從總線(bus)上遍歷各個設備,看驅動程序是否與其相匹配,如果匹配就將兩者邦定。這就是platform_driver_register() 
(2)先安裝USB驅動程序,然後當有USB設備插入時,那麼就遍歷總線(bus)上的各個驅動,看兩者是否匹配,如果匹配就將其綁定。這就是 platform_device_register() 函數


//----------------------------------------------------------------------------------------
Refer to: ( 我認為 welkinchen 解釋的最好)
1. http://welkinchen.pixnet.net/blog/post/46943070-platform-device
2.






2017年9月29日 星期五

What does "struct device;" mean?


kernel/include/linux/device.h
...
struct device;
struct device_private;
struct device_driver;
...
struct device_driver {
const char *name;
struct bus_type *bus;

struct module *owner;
const char *mod_name; /* used for built-in modules */

bool suppress_bind_attrs; /* disables bind/unbind via sysfs */
enum probe_type probe_type;

const struct of_device_id *of_match_table;
const struct acpi_device_id *acpi_match_table;

int (*probe) (struct device *dev);
int (*remove) (struct device *dev);
void (*shutdown) (struct device *dev);
int (*suspend) (struct device *dev, pm_message_t state);
int (*resume) (struct device *dev);
const struct attribute_group **groups;

const struct dev_pm_ops *pm;

struct driver_private *p;
};

struct device {
struct device *parent;

struct device_private *p;

struct kobject kobj;
const char *init_name; /* initial name of the device */
const struct device_type *type;

struct mutex mutex; /* mutex to synchronize calls to
* its driver.
*/

struct bus_type *bus; /* type of bus device is on */
struct device_driver *driver; /* which driver has allocated this
  device */
void *platform_data; /* Platform specific data, device
  core doesn't touch it */
void *driver_data; /* Driver data, set and get with
  dev_set/get_drvdata */
struct dev_pm_info power;
struct dev_pm_domain *pm_domain;

#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
struct irq_domain *msi_domain;
#endif
#ifdef CONFIG_PINCTRL
struct dev_pin_info *pins;
#endif
#ifdef CONFIG_GENERIC_MSI_IRQ
struct list_head msi_list;
#endif

#ifdef CONFIG_NUMA
int numa_node; /* NUMA node this device is close to */
#endif
u64 *dma_mask; /* dma mask (if dma'able device) */
u64 coherent_dma_mask;/* Like dma_mask, but for
    alloc_coherent mappings as
    not all hardware supports
    64 bit addresses for consistent
    allocations such descriptors. */
unsigned long dma_pfn_offset;

struct device_dma_parameters *dma_parms;

struct list_head dma_pools; /* dma pools (if dma'ble) */

struct dma_coherent_mem *dma_mem; /* internal for coherent mem
    override */
#ifdef CONFIG_DMA_CMA
struct cma *cma_area; /* contiguous memory area for dma
  allocations */
#endif
/* arch specific additions */
struct dev_archdata archdata;

struct device_node *of_node; /* associated device tree node */
struct fwnode_handle *fwnode; /* firmware device node */

dev_t devt; /* dev_t, creates the sysfs "dev" */
u32 id; /* device instance */

spinlock_t devres_lock;
struct list_head devres_head;

struct klist_node knode_class;
struct class *class;
const struct attribute_group **groups; /* optional groups */

void (*release)(struct device *dev);
struct iommu_group *iommu_group;

bool offline_disabled:1;
bool offline:1;
};

"struct device;" means that it is a declaration.

2017年9月27日 星期三

How to list all installed packages (CentOS & Ubuntu)


CentOS (Yellowdog Updater, Modified)
sudo yum list installed





Ubuntu
sudo apt list --installed

2017年9月22日 星期五

Linux driver GPIO ownership

gpio_request() : Use test and set to verify GPIO and get ownership
gpio_free() : Release ownership
-----------------------------------------------------------------------------------
int gpio_request(unsigned gpio, const char *label)
{
    struct gpio_desc    *desc;
    struct gpio_chip    *chip;
    int         status = -EPROBE_DEFER;
    unsigned long       flags;
    spin_lock_irqsave(&gpio_lock, flags);
    if (!gpio_is_valid(gpio)) {
        status = -EINVAL;
        goto done;
    }
    desc = &gpio_desc[gpio];
    chip = desc->chip;
    if (chip == NULL)
        goto done;
    if (!try_module_get(chip->owner))
        goto done;
    /* NOTE:  gpio_request() can be called in early boot,
     * before IRQs are enabled, for non-sleeping (SOC) GPIOs.
     */
    if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {
        desc_set_label(desc, label ? : "?");
        status = 0;
    } else {
        status = -EBUSY;
        module_put(chip->owner);
        goto done;
    }
    if (chip->request) {
        /* chip->request may sleep */
        spin_unlock_irqrestore(&gpio_lock, flags);
        status = chip->request(chip, gpio - chip->base);
        spin_lock_irqsave(&gpio_lock, flags);
        if (status < 0) {
            desc_set_label(desc, NULL);
            module_put(chip->owner);
            clear_bit(FLAG_REQUESTED, &desc->flags);
            goto done;
        }
    }
    if (chip->get_direction) {
        /* chip->get_direction may sleep */
        spin_unlock_irqrestore(&gpio_lock, flags);
        gpio_get_direction(gpio);
        spin_lock_irqsave(&gpio_lock, flags);
    }
done:
    if (status)
        pr_debug("gpio_request: gpio-%d (%s) status %d\n",
            gpio, label ? : "?", status);
    spin_unlock_irqrestore(&gpio_lock, flags);
    return status;
}
EXPORT_SYMBOL_GPL(gpio_request);

-----------------------------------------------------------------------------------
void gpio_free(unsigned gpio) { unsigned long flags; struct gpio_desc *desc; struct gpio_chip *chip; might_sleep(); if (!gpio_is_valid(gpio)) { WARN_ON(extra_checks); return; } gpio_unexport(gpio); spin_lock_irqsave(&gpio_lock, flags); desc = &gpio_desc[gpio]; chip = desc->chip; if (chip && test_bit(FLAG_REQUESTED, &desc->flags)) { if (chip->free) { spin_unlock_irqrestore(&gpio_lock, flags); might_sleep_if(extra_checks && chip->can_sleep); chip->free(chip, gpio - chip->base); spin_lock_irqsave(&gpio_lock, flags); } desc_set_label(desc, NULL); module_put(desc->chip->owner); clear_bit(FLAG_ACTIVE_LOW, &desc->flags); clear_bit(FLAG_REQUESTED, &desc->flags); } else WARN_ON(extra_checks); spin_unlock_irqrestore(&gpio_lock, flags); } EXPORT_SYMBOL_GPL(gpio_free);
-----------------------------------------------------------------------------------
Refer to: