cregit-Linux how code gets into the kernel

Release 4.18 drivers/staging/greybus/arche-platform.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Arche Platform driver to enable Unipro link.
 *
 * Copyright 2014-2015 Google Inc.
 * Copyright 2014-2015 Linaro Ltd.
 */

#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/suspend.h>
#include <linux/time.h>
#include "arche_platform.h"
#include "greybus.h"

#if IS_ENABLED(CONFIG_USB_HSIC_USB3613)
#include <linux/usb/usb3613.h>
#else

static inline int usb3613_hub_mode_ctrl(bool unused) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Johan Hovold13100.00%1100.00%
Total13100.00%1100.00%

#endif #define WD_COLDBOOT_PULSE_WIDTH_MS 30 enum svc_wakedetect_state { WD_STATE_IDLE, /* Default state = pulled high/low */ WD_STATE_BOOT_INIT, /* WD = falling edge (low) */ WD_STATE_COLDBOOT_TRIG, /* WD = rising edge (high), > 30msec */ WD_STATE_STANDBYBOOT_TRIG, /* As of now not used ?? */ WD_STATE_COLDBOOT_START, /* Cold boot process started */ WD_STATE_STANDBYBOOT_START, /* Not used */ }; struct arche_platform_drvdata { /* Control GPIO signals to and from AP <=> SVC */ int svc_reset_gpio; bool is_reset_act_hi; int svc_sysboot_gpio; int wake_detect_gpio; /* bi-dir,maps to WAKE_MOD & WAKE_FRAME signals */ enum arche_platform_state state; int svc_refclk_req; struct clk *svc_ref_clk; struct pinctrl *pinctrl; struct pinctrl_state *pin_default; int num_apbs; enum svc_wakedetect_state wake_detect_state; int wake_detect_irq; spinlock_t wake_lock; /* Protect wake_detect_state */ struct mutex platform_state_mutex; /* Protect state */ unsigned long wake_detect_start; struct notifier_block pm_notifier; struct device *dev; }; /* Requires calling context to hold arche_pdata->platform_state_mutex */
static void arche_platform_set_state(struct arche_platform_drvdata *arche_pdata, enum arche_platform_state state) { arche_pdata->state = state; }

Contributors

PersonTokensPropCommitsCommitProp
Bryan O'Donoghue21100.00%1100.00%
Total21100.00%1100.00%

/* Requires arche_pdata->wake_lock is held by calling context */
static void arche_platform_set_wake_detect_state( struct arche_platform_drvdata *arche_pdata, enum svc_wakedetect_state state) { arche_pdata->wake_detect_state = state; }

Contributors

PersonTokensPropCommitsCommitProp
Bryan O'Donoghue21100.00%1100.00%
Total21100.00%1100.00%


static inline void svc_reset_onoff(unsigned int gpio, bool onoff) { gpio_set_value(gpio, onoff); }

Contributors

PersonTokensPropCommitsCommitProp
Vaibhav Hiremath21100.00%2100.00%
Total21100.00%2100.00%


static int apb_cold_boot(struct device *dev, void *data) { int ret; ret = apb_ctrl_coldboot(dev); if (ret) dev_warn(dev, "failed to coldboot\n"); /*Child nodes are independent, so do not exit coldboot operation */ return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Vaibhav Hiremath40100.00%1100.00%
Total40100.00%1100.00%


static int apb_poweroff(struct device *dev, void *data) { apb_ctrl_poweroff(dev); /* Enable HUB3613 into HUB mode. */ if (usb3613_hub_mode_ctrl(false)) dev_warn(dev, "failed to control hub device\n"); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Vaibhav Hiremath38100.00%2100.00%
Total38100.00%2100.00%


static void arche_platform_wd_irq_en(struct arche_platform_drvdata *arche_pdata) { /* Enable interrupt here, to read event back from SVC */ gpio_direction_input(arche_pdata->wake_detect_gpio); enable_irq(arche_pdata->wake_detect_irq); }

Contributors

PersonTokensPropCommitsCommitProp
Vaibhav Hiremath26100.00%2100.00%
Total26100.00%2100.00%


static irqreturn_t arche_platform_wd_irq_thread(int irq, void *devid) { struct arche_platform_drvdata *arche_pdata = devid; unsigned long flags; spin_lock_irqsave(&arche_pdata->wake_lock, flags); if (arche_pdata->wake_detect_state != WD_STATE_COLDBOOT_TRIG) { /* Something is wrong */ spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); return IRQ_HANDLED; } arche_platform_set_wake_detect_state(arche_pdata, WD_STATE_COLDBOOT_START); spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); /* It should complete power cycle, so first make sure it is poweroff */ device_for_each_child(arche_pdata->dev, NULL, apb_poweroff); /* Bring APB out of reset: cold boot sequence */ device_for_each_child(arche_pdata->dev, NULL, apb_cold_boot); /* Enable HUB3613 into HUB mode. */ if (usb3613_hub_mode_ctrl(true)) dev_warn(arche_pdata->dev, "failed to control hub device\n"); spin_lock_irqsave(&arche_pdata->wake_lock, flags); arche_platform_set_wake_detect_state(arche_pdata, WD_STATE_IDLE); spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); return IRQ_HANDLED; }

Contributors

PersonTokensPropCommitsCommitProp
Vaibhav Hiremath13894.52%480.00%
Bryan O'Donoghue85.48%120.00%
Total146100.00%5100.00%


static irqreturn_t arche_platform_wd_irq(int irq, void *devid) { struct arche_platform_drvdata *arche_pdata = devid; unsigned long flags; spin_lock_irqsave(&arche_pdata->wake_lock, flags); if (gpio_get_value(arche_pdata->wake_detect_gpio)) { /* wake/detect rising */ /* * If wake/detect line goes high after low, within less than * 30msec, then standby boot sequence is initiated, which is not * supported/implemented as of now. So ignore it. */ if (arche_pdata->wake_detect_state == WD_STATE_BOOT_INIT) { if (time_before(jiffies, arche_pdata->wake_detect_start + msecs_to_jiffies(WD_COLDBOOT_PULSE_WIDTH_MS))) { arche_platform_set_wake_detect_state(arche_pdata, WD_STATE_IDLE); } else { /* * Check we are not in middle of irq thread * already */ if (arche_pdata->wake_detect_state != WD_STATE_COLDBOOT_START) { arche_platform_set_wake_detect_state(arche_pdata, WD_STATE_COLDBOOT_TRIG); spin_unlock_irqrestore( &arche_pdata->wake_lock, flags); return IRQ_WAKE_THREAD; } } } } else { /* wake/detect falling */ if (arche_pdata->wake_detect_state == WD_STATE_IDLE) { arche_pdata->wake_detect_start = jiffies; /* * In the beginning, when wake/detect goes low * (first time), we assume it is meant for coldboot * and set the flag. If wake/detect line stays low * beyond 30msec, then it is coldboot else fallback * to standby boot. */ arche_platform_set_wake_detect_state(arche_pdata, WD_STATE_BOOT_INIT); } } spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); return IRQ_HANDLED; }

Contributors

PersonTokensPropCommitsCommitProp
Vaibhav Hiremath14391.08%240.00%
Bryan O'Donoghue127.64%120.00%
Eames Trinh10.64%120.00%
Mitchell Tasman10.64%120.00%
Total157100.00%5100.00%

/* * Requires arche_pdata->platform_state_mutex to be held */
static int arche_platform_coldboot_seq(struct arche_platform_drvdata *arche_pdata) { int ret; if (arche_pdata->state == ARCHE_PLATFORM_STATE_ACTIVE) return 0; dev_info(arche_pdata->dev, "Booting from cold boot state\n"); svc_reset_onoff(arche_pdata->svc_reset_gpio, arche_pdata->is_reset_act_hi); gpio_set_value(arche_pdata->svc_sysboot_gpio, 0); usleep_range(100, 200); ret = clk_prepare_enable(arche_pdata->svc_ref_clk); if (ret) { dev_err(arche_pdata->dev, "failed to enable svc_ref_clk: %d\n", ret); return ret; } /* bring SVC out of reset */ svc_reset_onoff(arche_pdata->svc_reset_gpio, !arche_pdata->is_reset_act_hi); arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_ACTIVE); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Vaibhav Hiremath10996.46%375.00%
Bryan O'Donoghue43.54%125.00%
Total113100.00%4100.00%

/* * Requires arche_pdata->platform_state_mutex to be held */
static int arche_platform_fw_flashing_seq(struct arche_platform_drvdata *arche_pdata) { int ret; if (arche_pdata->state == ARCHE_PLATFORM_STATE_FW_FLASHING) return 0; dev_info(arche_pdata->dev, "Switching to FW flashing state\n"); svc_reset_onoff(arche_pdata->svc_reset_gpio, arche_pdata->is_reset_act_hi); gpio_set_value(arche_pdata->svc_sysboot_gpio, 1); usleep_range(100, 200); ret = clk_prepare_enable(arche_pdata->svc_ref_clk); if (ret) { dev_err(arche_pdata->dev, "failed to enable svc_ref_clk: %d\n", ret); return ret; } svc_reset_onoff(arche_pdata->svc_reset_gpio, !arche_pdata->is_reset_act_hi); arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_FW_FLASHING); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Vaibhav Hiremath10896.43%480.00%
Bryan O'Donoghue43.57%120.00%
Total112100.00%5100.00%

/* * Requires arche_pdata->platform_state_mutex to be held */
static void arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pdata) { unsigned long flags; if (arche_pdata->state == ARCHE_PLATFORM_STATE_OFF) return; /* If in fw_flashing mode, then no need to repeate things again */ if (arche_pdata->state != ARCHE_PLATFORM_STATE_FW_FLASHING) { disable_irq(arche_pdata->wake_detect_irq); spin_lock_irqsave(&arche_pdata->wake_lock, flags); arche_platform_set_wake_detect_state(arche_pdata, WD_STATE_IDLE); spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); } clk_disable_unprepare(arche_pdata->svc_ref_clk); /* As part of exit, put APB back in reset state */ svc_reset_onoff(arche_pdata->svc_reset_gpio, arche_pdata->is_reset_act_hi); arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_OFF); }

Contributors

PersonTokensPropCommitsCommitProp
Vaibhav Hiremath8791.58%1392.86%
Bryan O'Donoghue88.42%17.14%
Total95100.00%14100.00%


static ssize_t state_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct arche_platform_drvdata *arche_pdata = dev_get_drvdata(dev); int ret = 0; mutex_lock(&arche_pdata->platform_state_mutex); if (sysfs_streq(buf, "off")) { if (arche_pdata->state == ARCHE_PLATFORM_STATE_OFF) goto exit; /* If SVC goes down, bring down APB's as well */ device_for_each_child(arche_pdata->dev, NULL, apb_poweroff); arche_platform_poweroff_seq(arche_pdata); } else if (sysfs_streq(buf, "active")) { if (arche_pdata->state == ARCHE_PLATFORM_STATE_ACTIVE) goto exit; /* First we want to make sure we power off everything * and then activate back again */ device_for_each_child(arche_pdata->dev, NULL, apb_poweroff); arche_platform_poweroff_seq(arche_pdata); arche_platform_wd_irq_en(arche_pdata); ret = arche_platform_coldboot_seq(arche_pdata); if (ret) goto exit; } else if (sysfs_streq(buf, "standby")) { if (arche_pdata->state == ARCHE_PLATFORM_STATE_STANDBY) goto exit; dev_warn(arche_pdata->dev, "standby state not supported\n"); } else if (sysfs_streq(buf, "fw_flashing")) { if (arche_pdata->state == ARCHE_PLATFORM_STATE_FW_FLASHING) goto exit; /* * Here we only control SVC. * * In case of FW_FLASHING mode we do not want to control * APBs, as in case of V2, SPI bus is shared between both * the APBs. So let user chose which APB he wants to flash. */ arche_platform_poweroff_seq(arche_pdata); ret = arche_platform_fw_flashing_seq(arche_pdata); if (ret) goto exit; } else { dev_err(arche_pdata->dev, "unknown state\n"); ret = -EINVAL; } exit: mutex_unlock(&arche_pdata->platform_state_mutex); return ret ? ret : count; }

Contributors

PersonTokensPropCommitsCommitProp
Vaibhav Hiremath25198.82%1083.33%
Wolfram Sang20.79%18.33%
Elise Lennion10.39%18.33%
Total254100.00%12100.00%


static ssize_t state_show(struct device *dev, struct device_attribute *attr, char *buf) { struct arche_platform_drvdata *arche_pdata = dev_get_drvdata(dev); switch (arche_pdata->state) { case ARCHE_PLATFORM_STATE_OFF: return sprintf(buf, "off\n"); case ARCHE_PLATFORM_STATE_ACTIVE: return sprintf(buf, "active\n"); case ARCHE_PLATFORM_STATE_STANDBY: return sprintf(buf, "standby\n"); case ARCHE_PLATFORM_STATE_FW_FLASHING: return sprintf(buf, "fw_flashing\n"); default: return sprintf(buf, "unknown state\n"); } }

Contributors

PersonTokensPropCommitsCommitProp
Vaibhav Hiremath91100.00%2100.00%
Total91100.00%2100.00%

static DEVICE_ATTR_RW(state);
static int arche_platform_pm_notifier(struct notifier_block *notifier, unsigned long pm_event, void *unused) { struct arche_platform_drvdata *arche_pdata = container_of(notifier, struct arche_platform_drvdata, pm_notifier); int ret = NOTIFY_DONE; mutex_lock(&arche_pdata->platform_state_mutex); switch (pm_event) { case PM_SUSPEND_PREPARE: if (arche_pdata->state != ARCHE_PLATFORM_STATE_ACTIVE) { ret = NOTIFY_STOP; break; } device_for_each_child(arche_pdata->dev, NULL, apb_poweroff); arche_platform_poweroff_seq(arche_pdata); break; case PM_POST_SUSPEND: if (arche_pdata->state != ARCHE_PLATFORM_STATE_OFF) break; arche_platform_wd_irq_en(arche_pdata); arche_platform_coldboot_seq(arche_pdata); break; default: break; } mutex_unlock(&arche_pdata->platform_state_mutex); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
David Lin8568.55%120.00%
Vaibhav Hiremath3931.45%480.00%
Total124100.00%5100.00%


static int arche_platform_probe(struct platform_device *pdev) { struct arche_platform_drvdata *arche_pdata; struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; int ret; arche_pdata = devm_kzalloc(&pdev->dev, sizeof(*arche_pdata), GFP_KERNEL); if (!arche_pdata) return -ENOMEM; /* setup svc reset gpio */ arche_pdata->is_reset_act_hi = of_property_read_bool(np, "svc,reset-active-high"); arche_pdata->svc_reset_gpio = of_get_named_gpio(np, "svc,reset-gpio", 0); if (!gpio_is_valid(arche_pdata->svc_reset_gpio)) { dev_err(dev, "failed to get reset-gpio\n"); return arche_pdata->svc_reset_gpio; } ret = devm_gpio_request(dev, arche_pdata->svc_reset_gpio, "svc-reset"); if (ret) { dev_err(dev, "failed to request svc-reset gpio:%d\n", ret); return ret; } ret = gpio_direction_output(arche_pdata->svc_reset_gpio, arche_pdata->is_reset_act_hi); if (ret) { dev_err(dev, "failed to set svc-reset gpio dir:%d\n", ret); return ret; } arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_OFF); arche_pdata->svc_sysboot_gpio = of_get_named_gpio(np, "svc,sysboot-gpio", 0); if (!gpio_is_valid(arche_pdata->svc_sysboot_gpio)) { dev_err(dev, "failed to get sysboot gpio\n"); return arche_pdata->svc_sysboot_gpio; } ret = devm_gpio_request(dev, arche_pdata->svc_sysboot_gpio, "sysboot0"); if (ret) { dev_err(dev, "failed to request sysboot0 gpio:%d\n", ret); return ret; } ret = gpio_direction_output(arche_pdata->svc_sysboot_gpio, 0); if (ret) { dev_err(dev, "failed to set svc-reset gpio dir:%d\n", ret); return ret; } /* setup the clock request gpio first */ arche_pdata->svc_refclk_req = of_get_named_gpio(np, "svc,refclk-req-gpio", 0); if (!gpio_is_valid(arche_pdata->svc_refclk_req)) { dev_err(dev, "failed to get svc clock-req gpio\n"); return arche_pdata->svc_refclk_req; } ret = devm_gpio_request(dev, arche_pdata->svc_refclk_req, "svc-clk-req"); if (ret) { dev_err(dev, "failed to request svc-clk-req gpio: %d\n", ret); return ret; } ret = gpio_direction_input(arche_pdata->svc_refclk_req); if (ret) { dev_err(dev, "failed to set svc-clk-req gpio dir :%d\n", ret); return ret; } /* setup refclk2 to follow the pin */ arche_pdata->svc_ref_clk = devm_clk_get(dev, "svc_ref_clk"); if (IS_ERR(arche_pdata->svc_ref_clk)) { ret = PTR_ERR(arche_pdata->svc_ref_clk); dev_err(dev, "failed to get svc_ref_clk: %d\n", ret); return ret; } platform_set_drvdata(pdev, arche_pdata); arche_pdata->num_apbs = of_get_child_count(np); dev_dbg(dev, "Number of APB's available - %d\n", arche_pdata->num_apbs); arche_pdata->wake_detect_gpio = of_get_named_gpio(np, "svc,wake-detect-gpio", 0); if (arche_pdata->wake_detect_gpio < 0) { dev_err(dev, "failed to get wake detect gpio\n"); return arche_pdata->wake_detect_gpio; } ret = devm_gpio_request(dev, arche_pdata->wake_detect_gpio, "wake detect"); if (ret) { dev_err(dev, "Failed requesting wake_detect gpio %d\n", arche_pdata->wake_detect_gpio); return ret; } arche_platform_set_wake_detect_state(arche_pdata, WD_STATE_IDLE); arche_pdata->dev = &pdev->dev; spin_lock_init(&arche_pdata->wake_lock); mutex_init(&arche_pdata->platform_state_mutex); arche_pdata->wake_detect_irq = gpio_to_irq(arche_pdata->wake_detect_gpio); ret = devm_request_threaded_irq(dev, arche_pdata->wake_detect_irq, arche_platform_wd_irq, arche_platform_wd_irq_thread, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT, dev_name(dev), arche_pdata); if (ret) { dev_err(dev, "failed to request wake detect IRQ %d\n", ret); return ret; } disable_irq(arche_pdata->wake_detect_irq); ret = device_create_file(dev, &dev_attr_state); if (ret) { dev_err(dev, "failed to create state file in sysfs\n"); return ret; } ret = of_platform_populate(np, NULL, NULL, dev); if (ret) { dev_err(dev, "failed to populate child nodes %d\n", ret); goto err_device_remove; } arche_pdata->pm_notifier.notifier_call = arche_platform_pm_notifier; ret = register_pm_notifier(&arche_pdata->pm_notifier); if (ret) { dev_err(dev, "failed to register pm notifier %d\n", ret); goto err_device_remove; } /* Explicitly power off if requested */ if (!of_property_read_bool(pdev->dev.of_node, "arche,init-off")) { mutex_lock(&arche_pdata->platform_state_mutex); ret = arche_platform_coldboot_seq(arche_pdata); if (ret) { dev_err(dev, "Failed to cold boot svc %d\n", ret); goto err_coldboot; } arche_platform_wd_irq_en(arche_pdata); mutex_unlock(&arche_pdata->platform_state_mutex); } dev_info(dev, "Device registered successfully\n"); return 0; err_coldboot: mutex_unlock(&arche_pdata->platform_state_mutex); err_device_remove: device_remove_file(&pdev->dev, &dev_attr_state); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Vaibhav Hiremath73191.03%1463.64%
David Lin344.23%14.55%
Viresh Kumar151.87%29.09%
Arvind Yadav121.49%14.55%
Bryan O'Donoghue101.25%313.64%
Eva Rachel Retuya10.12%14.55%
Total803100.00%22100.00%


static int arche_remove_child(struct device *dev, void *unused) { struct platform_device *pdev = to_platform_device(dev); platform_device_unregister(pdev); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Vaibhav Hiremath33100.00%1100.00%
Total33100.00%1100.00%


static int arche_platform_remove(struct platform_device *pdev) { struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev); unregister_pm_notifier(&arche_pdata->pm_notifier); device_remove_file(&pdev->dev, &dev_attr_state); device_for_each_child(&pdev->dev, NULL, arche_remove_child); arche_platform_poweroff_seq(arche_pdata); if (usb3613_hub_mode_ctrl(false)) dev_warn(arche_pdata->dev, "failed to control hub device\n"); /* TODO: Should we do anything more here ?? */ return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Vaibhav Hiremath6989.61%685.71%
David Lin810.39%114.29%
Total77100.00%7100.00%


static __maybe_unused int arche_platform_suspend(struct device *dev) { /* * If timing profile premits, we may shutdown bridge * completely * * TODO: sequence ?? * * Also, need to make sure we meet precondition for unipro suspend * Precondition: Definition ??? */ return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Vaibhav Hiremath1593.75%266.67%
Arnd Bergmann16.25%133.33%
Total16100.00%3100.00%


static __maybe_unused int arche_platform_resume(struct device *dev) { /* * Atleast for ES2 we have to meet the delay requirement between * unipro switch and AP bridge init, depending on whether bridge is in * OFF state or standby state. * * Based on whether bridge is in standby or OFF state we may have to * assert multiple signals. Please refer to WDM spec, for more info. * */ return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Vaibhav Hiremath1593.75%266.67%
Arnd Bergmann16.25%133.33%
Total16100.00%3100.00%


static void arche_platform_shutdown(struct platform_device *pdev) { struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev); arche_platform_poweroff_seq(arche_pdata); usb3613_hub_mode_ctrl(false); }

Contributors

PersonTokensPropCommitsCommitProp
David Lin31100.00%1100.00%
Total31100.00%1100.00%

static SIMPLE_DEV_PM_OPS(arche_platform_pm_ops, arche_platform_suspend, arche_platform_resume); static const struct of_device_id arche_platform_of_match[] = { /* Use PID/VID of SVC device */ { .compatible = "google,arche-platform", }, { }, }; static const struct of_device_id arche_combined_id[] = { /* Use PID/VID of SVC device */ { .compatible = "google,arche-platform", }, { .compatible = "usbffff,2", }, { }, }; MODULE_DEVICE_TABLE(of, arche_combined_id); static struct platform_driver arche_platform_device_driver = { .probe = arche_platform_probe, .remove = arche_platform_remove, .shutdown = arche_platform_shutdown, .driver = { .name = "arche-platform-ctrl", .pm = &arche_platform_pm_ops, .of_match_table = arche_platform_of_match, } };
static int __init arche_init(void) { int retval; retval = platform_driver_register(&arche_platform_device_driver); if (retval) return retval; retval = arche_apb_init(); if (retval) platform_driver_unregister(&arche_platform_device_driver); return retval; }

Contributors

PersonTokensPropCommitsCommitProp
Greg Kroah-Hartman4395.56%150.00%
Viresh Kumar24.44%150.00%
Total45100.00%2100.00%

module_init(arche_init);
static void __exit arche_exit(void) { arche_apb_exit(); platform_driver_unregister(&arche_platform_device_driver); }

Contributors

PersonTokensPropCommitsCommitProp
Greg Kroah-Hartman1372.22%125.00%
Vaibhav Hiremath316.67%250.00%
Viresh Kumar211.11%125.00%
Total18100.00%4100.00%

module_exit(arche_exit); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Vaibhav Hiremath <vaibhav.hiremath@linaro.org>"); MODULE_DESCRIPTION("Arche Platform Driver");

Overall Contributors

PersonTokensPropCommitsCommitProp
Vaibhav Hiremath218283.44%3358.93%
David Lin1706.50%23.57%
Greg Kroah-Hartman953.63%35.36%
Bryan O'Donoghue933.56%35.36%
Viresh Kumar260.99%47.14%
Johan Hovold240.92%23.57%
Arvind Yadav120.46%11.79%
Eva Rachel Retuya30.11%23.57%
Mitchell Tasman30.11%11.79%
Wolfram Sang20.08%11.79%
Arnd Bergmann20.08%11.79%
Elise Lennion10.04%11.79%
Eames Trinh10.04%11.79%
Sandeep Patil10.04%11.79%
Gioh Kim0.00%00.00%
Total2615100.00%56100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.