mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
Staging driver updates for 7.4-rc1
Here is the big set of staging driver updates for 7.4-rc1.
The huge majority of changes in here were to the rtl8723bs driver, which
ended up being deleted entirely through the wifi driver tree, so while
the work here was nice to have done to get experience by people, the
overall goal was achieved in that we have a solid working and sane
driver in the real part of the tree now.
Other than that, included in here are:
- some greybus driver removal of broken drivers that no one ever used
- minor coding style cleanups for other staging drivers
All of these have been in linux-next with no reported issues, other than
the merge conflict of the driver being removed, but that's an obvious
one to resolve :)
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-----BEGIN PGP SIGNATURE-----
iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCatoUFQ8cZ3JlZ0Brcm9h
aC5jb20ACgkQMUfUDdst+yml3QCdGMayjqUnblAshQdo9aE4pvD2Pj4AoJKsgJwx
BhufWYg4PozRViFGJNbX
=+FvI
-----END PGP SIGNATURE-----
Merge tag 'staging-7.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging
Pull staging driver updates from Greg KH:
"Here is the big set of staging driver updates for 7.4-rc1.
The huge majority of changes in here were to the rtl8723bs driver,
which ended up being deleted entirely through the wifi driver tree, so
while the work here was nice to have done to get experience by people,
the overall goal was achieved in that we have a solid working and sane
driver in the real part of the tree now.
Other than that, included in here are:
- some greybus driver removal of broken drivers that no one ever used
- minor coding style cleanups for other staging drivers
All of these have been in linux-next with no reported issues, other
than the merge conflict of the driver being removed, but that's an
obvious one to resolve :)"
* tag 'staging-7.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (145 commits)
staging: rtl8723bs: remove unnecessary parentheses
rtl8723bs: Remove redundant macro in basic_types.h
staging: rtl8723bs: remove spaces before tabs in hal_com_reg.h
staging: greybus: Align function arguments
staging: greybus: uart: fix argument alignment
staging: greybus: Remove unused header declaration to_fw_mgmt_connection
staging: most: fix typo in driver_usage.txt
staging: vme_user: avoid iterator variable access outside list loop
staging: greybus: Remove unused function 'to_fw_mgmt_connection'
staging: greybus: replace PTR_ERR() with %pe in error messages
staging: octeon: fix misuse of kernel-doc comment
staging: nvec: fix GPIO descriptor documentation
staging: fbtft: update outdated struct fbtft_ops comment
greybus: Discard pm_runtime_put_autosuspend() return value
staging: rtl8723bs: remove unused defines in odm.h
staging: rtl8723bs: remove commented out code in hal/ files
staging: rtl8723bs: remove unused defines in HalBtcOutSrc.h
staging: rtl8723bs: remove unused PCI ASPM OSC definitions
staging: rtl8723bs: remove unused EEPROM definitions
staging: rtl8723bs: return bool from check_pending_xmitbuf
...
This commit is contained in:
commit
e1cff82880
4
CREDITS
4
CREDITS
|
|
@ -1717,6 +1717,10 @@ S: Talstr. 1
|
|||
S: D - 72072 Tuebingen
|
||||
S: Germany
|
||||
|
||||
N: Vaibhav Hiremath
|
||||
E: hvaibhav.linux@gmail.com
|
||||
D: Greybus Arche Platform driver
|
||||
|
||||
N: Richard Hirst
|
||||
E: richard@sleepie.demon.co.uk
|
||||
E: rhirst@linuxcare.com
|
||||
|
|
|
|||
|
|
@ -11449,13 +11449,6 @@ M: Bryan O'Donoghue <pure.logic@nexus-software.ie>
|
|||
S: Maintained
|
||||
F: drivers/staging/greybus/loopback.c
|
||||
|
||||
GREYBUS PLATFORM DRIVERS
|
||||
M: Vaibhav Hiremath <hvaibhav.linux@gmail.com>
|
||||
S: Maintained
|
||||
F: drivers/staging/greybus/arche-apb-ctrl.c
|
||||
F: drivers/staging/greybus/arche-platform.c
|
||||
F: drivers/staging/greybus/arche_platform.h
|
||||
|
||||
GREYBUS SDIO/GPIO/SPI PROTOCOLS DRIVERS
|
||||
M: Rui Miguel Silva <rmfrfs@gmail.com>
|
||||
S: Maintained
|
||||
|
|
|
|||
|
|
@ -212,9 +212,9 @@ static ssize_t axis_fifo_write(struct file *f, const char __user *buf,
|
|||
size_t len, loff_t *off)
|
||||
{
|
||||
struct axis_fifo *fifo = f->private_data;
|
||||
unsigned int words_to_write;
|
||||
size_t words_to_write;
|
||||
u32 *txbuf;
|
||||
int ret;
|
||||
ssize_t ret;
|
||||
|
||||
words_to_write = len / sizeof(u32);
|
||||
|
||||
|
|
@ -256,7 +256,7 @@ static ssize_t axis_fifo_write(struct file *f, const char __user *buf,
|
|||
goto end_unlock;
|
||||
}
|
||||
|
||||
for (int i = 0; i < words_to_write; ++i)
|
||||
for (size_t i = 0; i < words_to_write; ++i)
|
||||
iowrite32(txbuf[i], fifo->base_addr + XLLF_TDFD_OFFSET);
|
||||
|
||||
iowrite32(len, fifo->base_addr + XLLF_TLR_OFFSET);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* FB driver for the uPD161704 LCD Controller
|
||||
* FB driver for the BD663474 LCD Controller
|
||||
*
|
||||
* Copyright (C) 2014 Seong-Woo Kim
|
||||
*
|
||||
|
|
@ -166,6 +166,6 @@ MODULE_ALIAS("platform:" DRVNAME);
|
|||
MODULE_ALIAS("spi:bd663474");
|
||||
MODULE_ALIAS("platform:bd663474");
|
||||
|
||||
MODULE_DESCRIPTION("FB driver for the uPD161704 LCD Controller");
|
||||
MODULE_DESCRIPTION("FB driver for the BD663474 LCD Controller");
|
||||
MODULE_AUTHOR("Seong-Woo Kim");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ struct fbtft_par;
|
|||
* @write: Writes to interface bus
|
||||
* @read: Reads from interface bus
|
||||
* @write_vmem: Writes video memory to display
|
||||
* @write_reg: Writes to controller register
|
||||
* @write_register: Writes to controller register
|
||||
* @set_addr_win: Set the GRAM update window
|
||||
* @reset: Reset the LCD controller
|
||||
* @mkdirty: Marks display lines for update
|
||||
|
|
@ -46,7 +46,6 @@ struct fbtft_par;
|
|||
* @blank: Blank the display (optional)
|
||||
* @request_gpios_match: Do pinname to gpio matching
|
||||
* @request_gpios: Request gpios from the kernel
|
||||
* @free_gpios: Free previously requested gpios
|
||||
* @verify_gpios: Verify that necessary gpios is present (optional)
|
||||
* @register_backlight: Used to register backlight device (optional)
|
||||
* @unregister_backlight: Unregister backlight device (optional)
|
||||
|
|
|
|||
|
|
@ -32,16 +32,6 @@ config GREYBUS_BOOTROM
|
|||
To compile this code as a module, chose M here: the module
|
||||
will be called gb-bootrom.ko
|
||||
|
||||
config GREYBUS_CAMERA
|
||||
tristate "Greybus Camera Class driver"
|
||||
depends on MEDIA_SUPPORT && LEDS_CLASS_FLASH && BROKEN
|
||||
help
|
||||
Select this option if you have a device that follows the
|
||||
Greybus Camera Class specification.
|
||||
|
||||
To compile this code as a module, chose M here: the module
|
||||
will be called gb-camera.ko
|
||||
|
||||
config GREYBUS_FIRMWARE
|
||||
tristate "Greybus Firmware Download Class driver"
|
||||
depends on SPI
|
||||
|
|
@ -204,13 +194,4 @@ config GREYBUS_USB
|
|||
|
||||
endif # GREYBUS_BRIDGED_PHY
|
||||
|
||||
config GREYBUS_ARCHE
|
||||
tristate "Greybus Arche Platform driver"
|
||||
depends on USB_HSIC_USB3613 || COMPILE_TEST
|
||||
help
|
||||
Select this option if you have an Arche device.
|
||||
|
||||
To compile this code as a module, chose M here: the module
|
||||
will be called gb-arche.ko
|
||||
|
||||
endif # GREYBUS
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ ccflags-y += -I$(src)
|
|||
|
||||
# Greybus class drivers
|
||||
gb-bootrom-y := bootrom.o
|
||||
gb-camera-y := camera.o
|
||||
gb-firmware-y := fw-core.o fw-download.o fw-management.o authentication.o
|
||||
gb-spilib-y := spilib.o
|
||||
gb-hid-y := hid.o
|
||||
|
|
@ -16,7 +15,6 @@ gb-raw-y := raw.o
|
|||
gb-vibrator-y := vibrator.o
|
||||
|
||||
obj-$(CONFIG_GREYBUS_BOOTROM) += gb-bootrom.o
|
||||
obj-$(CONFIG_GREYBUS_CAMERA) += gb-camera.o
|
||||
obj-$(CONFIG_GREYBUS_FIRMWARE) += gb-firmware.o gb-spilib.o
|
||||
obj-$(CONFIG_GREYBUS_HID) += gb-hid.o
|
||||
obj-$(CONFIG_GREYBUS_LIGHT) += gb-light.o
|
||||
|
|
@ -65,9 +63,3 @@ obj-$(CONFIG_GREYBUS_SDIO) += gb-sdio.o
|
|||
obj-$(CONFIG_GREYBUS_SPI) += gb-spi.o gb-spilib.o
|
||||
obj-$(CONFIG_GREYBUS_UART) += gb-uart.o
|
||||
obj-$(CONFIG_GREYBUS_USB) += gb-usb.o
|
||||
|
||||
|
||||
# Greybus Platform driver
|
||||
gb-arche-y := arche-platform.o arche-apb-ctrl.o
|
||||
|
||||
obj-$(CONFIG_GREYBUS_ARCHE) += gb-arche.o
|
||||
|
|
|
|||
|
|
@ -1,490 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Arche Platform driver to control APB.
|
||||
*
|
||||
* Copyright 2014-2015 Google Inc.
|
||||
* Copyright 2014-2015 Linaro Ltd.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include "arche_platform.h"
|
||||
|
||||
static void apb_bootret_deassert(struct device *dev);
|
||||
|
||||
struct arche_apb_ctrl_drvdata {
|
||||
/* Control GPIO signals to and from AP <=> AP Bridges */
|
||||
struct gpio_desc *resetn;
|
||||
struct gpio_desc *boot_ret;
|
||||
struct gpio_desc *pwroff;
|
||||
struct gpio_desc *wake_in;
|
||||
struct gpio_desc *wake_out;
|
||||
struct gpio_desc *pwrdn;
|
||||
|
||||
enum arche_platform_state state;
|
||||
bool init_disabled;
|
||||
|
||||
struct regulator *vcore;
|
||||
struct regulator *vio;
|
||||
|
||||
struct gpio_desc *clk_en;
|
||||
struct clk *clk;
|
||||
|
||||
struct pinctrl *pinctrl;
|
||||
struct pinctrl_state *pin_default;
|
||||
|
||||
/* V2: SPI Bus control */
|
||||
struct gpio_desc *spi_en;
|
||||
bool spi_en_polarity_high;
|
||||
};
|
||||
|
||||
/*
|
||||
* Note that these low level api's are active high
|
||||
*/
|
||||
static inline void deassert_reset(struct gpio_desc *gpio)
|
||||
{
|
||||
gpiod_set_raw_value(gpio, 1);
|
||||
}
|
||||
|
||||
static inline void assert_reset(struct gpio_desc *gpio)
|
||||
{
|
||||
gpiod_set_raw_value(gpio, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: Please do not modify the below sequence, as it is as per the spec
|
||||
*/
|
||||
static int coldboot_seq(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev);
|
||||
int ret;
|
||||
|
||||
if (apb->init_disabled ||
|
||||
apb->state == ARCHE_PLATFORM_STATE_ACTIVE)
|
||||
return 0;
|
||||
|
||||
/* Hold APB in reset state */
|
||||
assert_reset(apb->resetn);
|
||||
|
||||
if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING && apb->spi_en)
|
||||
devm_gpiod_put(dev, apb->spi_en);
|
||||
|
||||
/* Enable power to APB */
|
||||
if (!IS_ERR(apb->vcore)) {
|
||||
ret = regulator_enable(apb->vcore);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable core regulator\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (!IS_ERR(apb->vio)) {
|
||||
ret = regulator_enable(apb->vio);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable IO regulator\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
apb_bootret_deassert(dev);
|
||||
|
||||
/* On DB3 clock was not mandatory */
|
||||
if (apb->clk_en)
|
||||
gpiod_set_value(apb->clk_en, 1);
|
||||
|
||||
usleep_range(100, 200);
|
||||
|
||||
/* deassert reset to APB : Active-low signal */
|
||||
deassert_reset(apb->resetn);
|
||||
|
||||
apb->state = ARCHE_PLATFORM_STATE_ACTIVE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fw_flashing_seq(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev);
|
||||
int ret;
|
||||
|
||||
if (apb->init_disabled ||
|
||||
apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING)
|
||||
return 0;
|
||||
|
||||
ret = regulator_enable(apb->vcore);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable core regulator\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regulator_enable(apb->vio);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable IO regulator\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (apb->spi_en) {
|
||||
unsigned long flags;
|
||||
|
||||
if (apb->spi_en_polarity_high)
|
||||
flags = GPIOD_OUT_HIGH;
|
||||
else
|
||||
flags = GPIOD_OUT_LOW;
|
||||
|
||||
apb->spi_en = devm_gpiod_get(dev, "spi-en", flags);
|
||||
if (IS_ERR(apb->spi_en)) {
|
||||
ret = PTR_ERR(apb->spi_en);
|
||||
dev_err(dev, "Failed requesting SPI bus en GPIO: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* for flashing device should be in reset state */
|
||||
assert_reset(apb->resetn);
|
||||
apb->state = ARCHE_PLATFORM_STATE_FW_FLASHING;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int standby_boot_seq(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev);
|
||||
|
||||
if (apb->init_disabled)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Even if it is in OFF state,
|
||||
* then we do not want to change the state
|
||||
*/
|
||||
if (apb->state == ARCHE_PLATFORM_STATE_STANDBY ||
|
||||
apb->state == ARCHE_PLATFORM_STATE_OFF)
|
||||
return 0;
|
||||
|
||||
if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING && apb->spi_en)
|
||||
devm_gpiod_put(dev, apb->spi_en);
|
||||
|
||||
/*
|
||||
* As per WDM spec, do nothing
|
||||
*
|
||||
* Pasted from WDM spec,
|
||||
* - A falling edge on POWEROFF_L is detected (a)
|
||||
* - WDM enters standby mode, but no output signals are changed
|
||||
*/
|
||||
|
||||
/* TODO: POWEROFF_L is input to WDM module */
|
||||
apb->state = ARCHE_PLATFORM_STATE_STANDBY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void poweroff_seq(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev);
|
||||
|
||||
if (apb->init_disabled || apb->state == ARCHE_PLATFORM_STATE_OFF)
|
||||
return;
|
||||
|
||||
if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING && apb->spi_en)
|
||||
devm_gpiod_put(dev, apb->spi_en);
|
||||
|
||||
/* disable the clock */
|
||||
if (apb->clk_en)
|
||||
gpiod_set_value(apb->clk_en, 0);
|
||||
|
||||
if (!IS_ERR(apb->vcore) && regulator_is_enabled(apb->vcore) > 0)
|
||||
regulator_disable(apb->vcore);
|
||||
|
||||
if (!IS_ERR(apb->vio) && regulator_is_enabled(apb->vio) > 0)
|
||||
regulator_disable(apb->vio);
|
||||
|
||||
/* As part of exit, put APB back in reset state */
|
||||
assert_reset(apb->resetn);
|
||||
apb->state = ARCHE_PLATFORM_STATE_OFF;
|
||||
|
||||
/* TODO: May have to send an event to SVC about this exit */
|
||||
}
|
||||
|
||||
static void apb_bootret_deassert(struct device *dev)
|
||||
{
|
||||
struct arche_apb_ctrl_drvdata *apb = dev_get_drvdata(dev);
|
||||
|
||||
gpiod_set_value(apb->boot_ret, 0);
|
||||
}
|
||||
|
||||
int apb_ctrl_coldboot(struct device *dev)
|
||||
{
|
||||
return coldboot_seq(to_platform_device(dev));
|
||||
}
|
||||
|
||||
int apb_ctrl_fw_flashing(struct device *dev)
|
||||
{
|
||||
return fw_flashing_seq(to_platform_device(dev));
|
||||
}
|
||||
|
||||
int apb_ctrl_standby_boot(struct device *dev)
|
||||
{
|
||||
return standby_boot_seq(to_platform_device(dev));
|
||||
}
|
||||
|
||||
void apb_ctrl_poweroff(struct device *dev)
|
||||
{
|
||||
poweroff_seq(to_platform_device(dev));
|
||||
}
|
||||
|
||||
static ssize_t state_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev);
|
||||
int ret = 0;
|
||||
bool is_disabled;
|
||||
|
||||
if (sysfs_streq(buf, "off")) {
|
||||
if (apb->state == ARCHE_PLATFORM_STATE_OFF)
|
||||
return count;
|
||||
|
||||
poweroff_seq(pdev);
|
||||
} else if (sysfs_streq(buf, "active")) {
|
||||
if (apb->state == ARCHE_PLATFORM_STATE_ACTIVE)
|
||||
return count;
|
||||
|
||||
poweroff_seq(pdev);
|
||||
is_disabled = apb->init_disabled;
|
||||
apb->init_disabled = false;
|
||||
ret = coldboot_seq(pdev);
|
||||
if (ret)
|
||||
apb->init_disabled = is_disabled;
|
||||
} else if (sysfs_streq(buf, "standby")) {
|
||||
if (apb->state == ARCHE_PLATFORM_STATE_STANDBY)
|
||||
return count;
|
||||
|
||||
ret = standby_boot_seq(pdev);
|
||||
} else if (sysfs_streq(buf, "fw_flashing")) {
|
||||
if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING)
|
||||
return count;
|
||||
|
||||
/*
|
||||
* First we want to make sure we power off everything
|
||||
* and then enter FW flashing state
|
||||
*/
|
||||
poweroff_seq(pdev);
|
||||
ret = fw_flashing_seq(pdev);
|
||||
} else {
|
||||
dev_err(dev, "unknown state\n");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret ? ret : count;
|
||||
}
|
||||
|
||||
static ssize_t state_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct arche_apb_ctrl_drvdata *apb = dev_get_drvdata(dev);
|
||||
|
||||
switch (apb->state) {
|
||||
case ARCHE_PLATFORM_STATE_OFF:
|
||||
return sysfs_emit(buf, "off%s\n",
|
||||
apb->init_disabled ? ",disabled" : "");
|
||||
case ARCHE_PLATFORM_STATE_ACTIVE:
|
||||
return sysfs_emit(buf, "active\n");
|
||||
case ARCHE_PLATFORM_STATE_STANDBY:
|
||||
return sysfs_emit(buf, "standby\n");
|
||||
case ARCHE_PLATFORM_STATE_FW_FLASHING:
|
||||
return sysfs_emit(buf, "fw_flashing\n");
|
||||
default:
|
||||
return sysfs_emit(buf, "unknown state\n");
|
||||
}
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RW(state);
|
||||
|
||||
static int apb_ctrl_get_fw_data(struct platform_device *pdev,
|
||||
struct arche_apb_ctrl_drvdata *apb)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
int ret;
|
||||
|
||||
apb->resetn = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(apb->resetn)) {
|
||||
ret = PTR_ERR(apb->resetn);
|
||||
dev_err(dev, "Failed requesting reset GPIO: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
apb->boot_ret = devm_gpiod_get(dev, "boot-ret", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(apb->boot_ret)) {
|
||||
ret = PTR_ERR(apb->boot_ret);
|
||||
dev_err(dev, "Failed requesting bootret GPIO: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* It's not mandatory to support power management interface */
|
||||
apb->pwroff = devm_gpiod_get_optional(dev, "pwr-off", GPIOD_IN);
|
||||
if (IS_ERR(apb->pwroff)) {
|
||||
ret = PTR_ERR(apb->pwroff);
|
||||
dev_err(dev, "Failed requesting pwroff_n GPIO: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Do not make clock mandatory as of now (for DB3) */
|
||||
apb->clk_en = devm_gpiod_get_optional(dev, "clock-en", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(apb->clk_en)) {
|
||||
ret = PTR_ERR(apb->clk_en);
|
||||
dev_err(dev, "Failed requesting APB clock en GPIO: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
apb->pwrdn = devm_gpiod_get(dev, "pwr-down", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(apb->pwrdn)) {
|
||||
ret = PTR_ERR(apb->pwrdn);
|
||||
dev_warn(dev, "Failed requesting power down GPIO: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Regulators are optional, as we may have fixed supply coming in */
|
||||
apb->vcore = devm_regulator_get(dev, "vcore");
|
||||
if (IS_ERR(apb->vcore))
|
||||
dev_warn(dev, "no core regulator found\n");
|
||||
|
||||
apb->vio = devm_regulator_get(dev, "vio");
|
||||
if (IS_ERR(apb->vio))
|
||||
dev_warn(dev, "no IO regulator found\n");
|
||||
|
||||
apb->pinctrl = devm_pinctrl_get(&pdev->dev);
|
||||
if (IS_ERR(apb->pinctrl)) {
|
||||
dev_err(&pdev->dev, "could not get pinctrl handle\n");
|
||||
return PTR_ERR(apb->pinctrl);
|
||||
}
|
||||
apb->pin_default = pinctrl_lookup_state(apb->pinctrl, "default");
|
||||
if (IS_ERR(apb->pin_default)) {
|
||||
dev_err(&pdev->dev, "could not get default pin state\n");
|
||||
return PTR_ERR(apb->pin_default);
|
||||
}
|
||||
|
||||
/* Only applicable for platform >= V2 */
|
||||
if (device_property_read_bool(&pdev->dev, "gb,spi-en-active-high"))
|
||||
apb->spi_en_polarity_high = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int arche_apb_ctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct arche_apb_ctrl_drvdata *apb;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
apb = devm_kzalloc(&pdev->dev, sizeof(*apb), GFP_KERNEL);
|
||||
if (!apb)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = apb_ctrl_get_fw_data(pdev, apb);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to get apb devicetree data %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Initially set APB to OFF state */
|
||||
apb->state = ARCHE_PLATFORM_STATE_OFF;
|
||||
/* Check whether device needs to be enabled on boot */
|
||||
if (device_property_read_bool(&pdev->dev, "arche,init-disable"))
|
||||
apb->init_disabled = true;
|
||||
|
||||
platform_set_drvdata(pdev, apb);
|
||||
|
||||
/* Create sysfs interface to allow user to change state dynamically */
|
||||
ret = device_create_file(dev, &dev_attr_state);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to create state file in sysfs\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "Device registered successfully\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void arche_apb_ctrl_remove(struct platform_device *pdev)
|
||||
{
|
||||
device_remove_file(&pdev->dev, &dev_attr_state);
|
||||
poweroff_seq(pdev);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
}
|
||||
|
||||
static int __maybe_unused arche_apb_ctrl_suspend(struct device *dev)
|
||||
{
|
||||
/*
|
||||
* If timing profile permits, we may shutdown bridge
|
||||
* completely
|
||||
*
|
||||
* TODO: sequence ??
|
||||
*
|
||||
* Also, need to make sure we meet precondition for unipro suspend
|
||||
* Precondition: Definition ???
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused arche_apb_ctrl_resume(struct device *dev)
|
||||
{
|
||||
/*
|
||||
* At least 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;
|
||||
}
|
||||
|
||||
static void arche_apb_ctrl_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
apb_ctrl_poweroff(&pdev->dev);
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(arche_apb_ctrl_pm_ops, arche_apb_ctrl_suspend,
|
||||
arche_apb_ctrl_resume);
|
||||
|
||||
static const struct of_device_id arche_apb_ctrl_of_match[] = {
|
||||
{ .compatible = "usbffff,2", },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, arche_apb_ctrl_of_match);
|
||||
|
||||
static struct platform_driver arche_apb_ctrl_device_driver = {
|
||||
.probe = arche_apb_ctrl_probe,
|
||||
.remove = arche_apb_ctrl_remove,
|
||||
.shutdown = arche_apb_ctrl_shutdown,
|
||||
.driver = {
|
||||
.name = "arche-apb-ctrl",
|
||||
.pm = &arche_apb_ctrl_pm_ops,
|
||||
.of_match_table = arche_apb_ctrl_of_match,
|
||||
}
|
||||
};
|
||||
|
||||
int __init arche_apb_init(void)
|
||||
{
|
||||
return platform_driver_register(&arche_apb_ctrl_device_driver);
|
||||
}
|
||||
|
||||
void __exit arche_apb_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&arche_apb_ctrl_device_driver);
|
||||
}
|
||||
|
|
@ -1,653 +0,0 @@
|
|||
// 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/consumer.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.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 <linux/greybus.h>
|
||||
#include <linux/of.h>
|
||||
#include "arche_platform.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;
|
||||
}
|
||||
#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 */
|
||||
struct gpio_desc *svc_reset;
|
||||
bool is_reset_act_hi;
|
||||
struct gpio_desc *svc_sysboot;
|
||||
struct gpio_desc *wake_detect; /* bi-dir,maps to WAKE_MOD & WAKE_FRAME signals */
|
||||
|
||||
enum arche_platform_state state;
|
||||
|
||||
struct gpio_desc *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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
static inline void svc_reset_onoff(struct gpio_desc *gpio, bool onoff)
|
||||
{
|
||||
gpiod_set_raw_value(gpio, onoff);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static void arche_platform_wd_irq_en(struct arche_platform_drvdata *arche_pdata)
|
||||
{
|
||||
/* Enable interrupt here, to read event back from SVC */
|
||||
enable_irq(arche_pdata->wake_detect_irq);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 (gpiod_get_value(arche_pdata->wake_detect)) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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, arche_pdata->is_reset_act_hi);
|
||||
|
||||
gpiod_set_value(arche_pdata->svc_sysboot, 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, !arche_pdata->is_reset_act_hi);
|
||||
|
||||
arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_ACTIVE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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, arche_pdata->is_reset_act_hi);
|
||||
|
||||
gpiod_set_value(arche_pdata->svc_sysboot, 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, !arche_pdata->is_reset_act_hi);
|
||||
|
||||
arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_FW_FLASHING);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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, arche_pdata->is_reset_act_hi);
|
||||
|
||||
arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_OFF);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 sysfs_emit(buf, "off\n");
|
||||
case ARCHE_PLATFORM_STATE_ACTIVE:
|
||||
return sysfs_emit(buf, "active\n");
|
||||
case ARCHE_PLATFORM_STATE_STANDBY:
|
||||
return sysfs_emit(buf, "standby\n");
|
||||
case ARCHE_PLATFORM_STATE_FW_FLASHING:
|
||||
return sysfs_emit(buf, "fw_flashing\n");
|
||||
default:
|
||||
return sysfs_emit(buf, "unknown state\n");
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
unsigned int flags;
|
||||
|
||||
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");
|
||||
if (arche_pdata->is_reset_act_hi)
|
||||
flags = GPIOD_OUT_HIGH;
|
||||
else
|
||||
flags = GPIOD_OUT_LOW;
|
||||
|
||||
arche_pdata->svc_reset = devm_gpiod_get(dev, "svc,reset", flags);
|
||||
if (IS_ERR(arche_pdata->svc_reset)) {
|
||||
ret = PTR_ERR(arche_pdata->svc_reset);
|
||||
dev_err(dev, "failed to request svc-reset GPIO: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_OFF);
|
||||
|
||||
arche_pdata->svc_sysboot = devm_gpiod_get(dev, "svc,sysboot",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(arche_pdata->svc_sysboot)) {
|
||||
ret = PTR_ERR(arche_pdata->svc_sysboot);
|
||||
dev_err(dev, "failed to request sysboot0 GPIO: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* setup the clock request gpio first */
|
||||
arche_pdata->svc_refclk_req = devm_gpiod_get(dev, "svc,refclk-req",
|
||||
GPIOD_IN);
|
||||
if (IS_ERR(arche_pdata->svc_refclk_req)) {
|
||||
ret = PTR_ERR(arche_pdata->svc_refclk_req);
|
||||
dev_err(dev, "failed to request svc-clk-req GPIO: %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 = devm_gpiod_get(dev, "svc,wake-detect",
|
||||
GPIOD_IN);
|
||||
if (IS_ERR(arche_pdata->wake_detect)) {
|
||||
ret = PTR_ERR(arche_pdata->wake_detect);
|
||||
dev_err(dev, "Failed requesting wake_detect GPIO: %d\n", ret);
|
||||
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 =
|
||||
gpiod_to_irq(arche_pdata->wake_detect);
|
||||
|
||||
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_depopulate;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
mutex_unlock(&arche_pdata->platform_state_mutex);
|
||||
dev_err(dev, "Failed to cold boot svc %d\n", ret);
|
||||
goto err_unregister_pm_notifier;
|
||||
}
|
||||
arche_platform_wd_irq_en(arche_pdata);
|
||||
mutex_unlock(&arche_pdata->platform_state_mutex);
|
||||
}
|
||||
|
||||
dev_info(dev, "Device registered successfully\n");
|
||||
return 0;
|
||||
|
||||
err_unregister_pm_notifier:
|
||||
unregister_pm_notifier(&arche_pdata->pm_notifier);
|
||||
err_depopulate:
|
||||
of_platform_depopulate(dev);
|
||||
err_device_remove:
|
||||
device_remove_file(&pdev->dev, &dev_attr_state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void 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);
|
||||
of_platform_depopulate(&pdev->dev);
|
||||
arche_platform_poweroff_seq(arche_pdata);
|
||||
|
||||
if (usb3613_hub_mode_ctrl(false))
|
||||
dev_warn(arche_pdata->dev, "failed to control hub device\n");
|
||||
}
|
||||
|
||||
static __maybe_unused int arche_platform_suspend(struct device *dev)
|
||||
{
|
||||
/*
|
||||
* If timing profile permits, we may shutdown bridge
|
||||
* completely
|
||||
*
|
||||
* TODO: define shutdown sequence
|
||||
*
|
||||
* Also, need to make sure we meet precondition for unipro suspend
|
||||
* Precondition: Definition ???
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __maybe_unused int arche_platform_resume(struct device *dev)
|
||||
{
|
||||
/*
|
||||
* At least 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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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", },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, arche_platform_of_match);
|
||||
|
||||
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;
|
||||
}
|
||||
module_init(arche_init);
|
||||
|
||||
static void __exit arche_exit(void)
|
||||
{
|
||||
arche_apb_exit();
|
||||
platform_driver_unregister(&arche_platform_device_driver);
|
||||
}
|
||||
module_exit(arche_exit);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("Vaibhav Hiremath <vaibhav.hiremath@linaro.org>");
|
||||
MODULE_DESCRIPTION("Arche Platform Driver");
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Arche Platform driver to enable Unipro link.
|
||||
*
|
||||
* Copyright 2015-2016 Google Inc.
|
||||
* Copyright 2015-2016 Linaro Ltd.
|
||||
*/
|
||||
|
||||
#ifndef __ARCHE_PLATFORM_H
|
||||
#define __ARCHE_PLATFORM_H
|
||||
|
||||
enum arche_platform_state {
|
||||
ARCHE_PLATFORM_STATE_OFF,
|
||||
ARCHE_PLATFORM_STATE_ACTIVE,
|
||||
ARCHE_PLATFORM_STATE_STANDBY,
|
||||
ARCHE_PLATFORM_STATE_FW_FLASHING,
|
||||
};
|
||||
|
||||
int __init arche_apb_init(void);
|
||||
void __exit arche_apb_exit(void);
|
||||
|
||||
/* Operational states for the APB device */
|
||||
int apb_ctrl_coldboot(struct device *dev);
|
||||
int apb_ctrl_fw_flashing(struct device *dev);
|
||||
int apb_ctrl_standby_boot(struct device *dev);
|
||||
void apb_ctrl_poweroff(struct device *dev);
|
||||
|
||||
#endif /* __ARCHE_PLATFORM_H */
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -22,7 +22,6 @@
|
|||
/* Firmware Management Protocol specific functions */
|
||||
int fw_mgmt_init(void);
|
||||
void fw_mgmt_exit(void);
|
||||
struct gb_connection *to_fw_mgmt_connection(struct device *dev);
|
||||
int gb_fw_mgmt_request_handler(struct gb_operation *op);
|
||||
int gb_fw_mgmt_connection_init(struct gb_connection *connection);
|
||||
void gb_fw_mgmt_connection_exit(struct gb_connection *connection);
|
||||
|
|
|
|||
|
|
@ -21,13 +21,6 @@ struct gb_fw_core {
|
|||
|
||||
static struct spilib_ops *spilib_ops;
|
||||
|
||||
struct gb_connection *to_fw_mgmt_connection(struct device *dev)
|
||||
{
|
||||
struct gb_fw_core *fw_core = dev_get_drvdata(dev);
|
||||
|
||||
return fw_core->mgmt_connection;
|
||||
}
|
||||
|
||||
static int gb_fw_spi_connection_init(struct gb_connection *connection)
|
||||
{
|
||||
int ret;
|
||||
|
|
@ -93,8 +86,8 @@ static int gb_fw_core_probe(struct gb_bundle *bundle,
|
|||
if (IS_ERR(connection)) {
|
||||
ret = PTR_ERR(connection);
|
||||
dev_err(&bundle->dev,
|
||||
"failed to create management connection (%d)\n",
|
||||
ret);
|
||||
"failed to create management connection (%pe)\n",
|
||||
connection);
|
||||
goto err_destroy_connections;
|
||||
}
|
||||
|
||||
|
|
@ -112,8 +105,8 @@ static int gb_fw_core_probe(struct gb_bundle *bundle,
|
|||
connection = gb_connection_create(bundle, cport_id,
|
||||
gb_fw_download_request_handler);
|
||||
if (IS_ERR(connection)) {
|
||||
dev_err(&bundle->dev, "failed to create download connection (%ld)\n",
|
||||
PTR_ERR(connection));
|
||||
dev_err(&bundle->dev, "failed to create download connection (%pe)\n",
|
||||
connection);
|
||||
} else {
|
||||
fw_core->download_connection = connection;
|
||||
}
|
||||
|
|
@ -131,8 +124,8 @@ static int gb_fw_core_probe(struct gb_bundle *bundle,
|
|||
connection = gb_connection_create(bundle, cport_id,
|
||||
NULL);
|
||||
if (IS_ERR(connection)) {
|
||||
dev_err(&bundle->dev, "failed to create SPI connection (%ld)\n",
|
||||
PTR_ERR(connection));
|
||||
dev_err(&bundle->dev, "failed to create SPI connection (%pe)\n",
|
||||
connection);
|
||||
} else {
|
||||
fw_core->spi_connection = connection;
|
||||
}
|
||||
|
|
@ -149,8 +142,8 @@ static int gb_fw_core_probe(struct gb_bundle *bundle,
|
|||
connection = gb_connection_create(bundle, cport_id,
|
||||
NULL);
|
||||
if (IS_ERR(connection)) {
|
||||
dev_err(&bundle->dev, "failed to create Authentication connection (%ld)\n",
|
||||
PTR_ERR(connection));
|
||||
dev_err(&bundle->dev, "failed to create Authentication connection (%pe)\n",
|
||||
connection);
|
||||
} else {
|
||||
fw_core->cap_connection = connection;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,127 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Greybus Camera protocol driver.
|
||||
*
|
||||
* Copyright 2015 Google Inc.
|
||||
*/
|
||||
#ifndef __GB_CAMERA_H
|
||||
#define __GB_CAMERA_H
|
||||
|
||||
#include <linux/v4l2-mediabus.h>
|
||||
|
||||
/* Input flags need to be set from the caller */
|
||||
#define GB_CAMERA_IN_FLAG_TEST BIT(0)
|
||||
/* Output flags returned */
|
||||
#define GB_CAMERA_OUT_FLAG_ADJUSTED BIT(0)
|
||||
|
||||
/**
|
||||
* struct gb_camera_stream - Represents greybus camera stream.
|
||||
* @width: Stream width in pixels.
|
||||
* @height: Stream height in pixels.
|
||||
* @pixel_code: Media bus pixel code.
|
||||
* @vc: MIPI CSI virtual channel.
|
||||
* @dt: MIPI CSI data types. Most formats use a single data type, in which case
|
||||
* the second element will be ignored.
|
||||
* @max_size: Maximum size of a frame in bytes. The camera module guarantees
|
||||
* that all data between the Frame Start and Frame End packet for
|
||||
* the associated virtual channel and data type(s) will not exceed
|
||||
* this size.
|
||||
*/
|
||||
struct gb_camera_stream {
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
enum v4l2_mbus_pixelcode pixel_code;
|
||||
unsigned int vc;
|
||||
unsigned int dt[2];
|
||||
unsigned int max_size;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct gb_camera_csi_params - CSI configuration parameters
|
||||
* @num_lanes: number of CSI data lanes
|
||||
* @clk_freq: CSI clock frequency in Hz
|
||||
*/
|
||||
struct gb_camera_csi_params {
|
||||
unsigned int num_lanes;
|
||||
unsigned int clk_freq;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct gb_camera_ops - Greybus camera operations, used by the Greybus camera
|
||||
* driver to expose operations to the host camera driver.
|
||||
* @capabilities: Retrieve camera capabilities and store them in the buffer
|
||||
* 'buf' capabilities. The buffer maximum size is specified by
|
||||
* the caller in the 'size' parameter, and the effective
|
||||
* capabilities size is returned from the function. If the buffer
|
||||
* size is too small to hold the capabilities an error is
|
||||
* returned and the buffer is left untouched.
|
||||
*
|
||||
* @configure_streams: Negotiate configuration and prepare the module for video
|
||||
* capture. The caller specifies the number of streams it
|
||||
* requests in the 'nstreams' argument and the associated
|
||||
* streams configurations in the 'streams' argument. The
|
||||
* GB_CAMERA_IN_FLAG_TEST 'flag' can be set to test a
|
||||
* configuration without applying it, otherwise the
|
||||
* configuration is applied by the module. The module can
|
||||
* decide to modify the requested configuration, including
|
||||
* using a different number of streams. In that case the
|
||||
* modified configuration won't be applied, the
|
||||
* GB_CAMERA_OUT_FLAG_ADJUSTED 'flag' will be set upon
|
||||
* return, and the modified configuration and number of
|
||||
* streams stored in 'streams' and 'array'. The module
|
||||
* returns its CSI-2 bus parameters in the 'csi_params'
|
||||
* structure in all cases.
|
||||
*
|
||||
* @capture: Submit a capture request. The supplied 'request_id' must be unique
|
||||
* and higher than the IDs of all the previously submitted requests.
|
||||
* The 'streams' argument specifies which streams are affected by the
|
||||
* request in the form of a bitmask, with bits corresponding to the
|
||||
* configured streams indexes. If the request contains settings, the
|
||||
* 'settings' argument points to the settings buffer and its size is
|
||||
* specified by the 'settings_size' argument. Otherwise the 'settings'
|
||||
* argument should be set to NULL and 'settings_size' to 0.
|
||||
*
|
||||
* @flush: Flush the capture requests queue. Return the ID of the last request
|
||||
* that will processed by the device before it stops transmitting video
|
||||
* frames. All queued capture requests with IDs higher than the returned
|
||||
* ID will be dropped without being processed.
|
||||
*/
|
||||
struct gb_camera_ops {
|
||||
ssize_t (*capabilities)(void *priv, char *buf, size_t len);
|
||||
int (*configure_streams)(void *priv, unsigned int *nstreams,
|
||||
unsigned int *flags,
|
||||
struct gb_camera_stream *streams,
|
||||
struct gb_camera_csi_params *csi_params);
|
||||
int (*capture)(void *priv, u32 request_id,
|
||||
unsigned int streams, unsigned int num_frames,
|
||||
size_t settings_size, const void *settings);
|
||||
int (*flush)(void *priv, u32 *request_id);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct gb_camera_module - Represents greybus camera module.
|
||||
* @priv: Module private data, passed to all camera operations.
|
||||
* @ops: Greybus camera operation callbacks.
|
||||
* @interface_id: Interface id of the module.
|
||||
* @refcount: Reference counting object.
|
||||
* @release: Module release function.
|
||||
* @list: List entry in the camera modules list.
|
||||
*/
|
||||
struct gb_camera_module {
|
||||
void *priv;
|
||||
const struct gb_camera_ops *ops;
|
||||
|
||||
unsigned int interface_id;
|
||||
struct kref refcount;
|
||||
void (*release)(struct kref *kref);
|
||||
struct list_head list; /* Global list */
|
||||
};
|
||||
|
||||
#define gb_camera_call(f, op, args...) \
|
||||
(!(f) ? -ENODEV : (((f)->ops->op) ? \
|
||||
(f)->ops->op((f)->priv, ##args) : -ENOIOCTLCMD))
|
||||
|
||||
int gb_camera_register(struct gb_camera_module *module);
|
||||
int gb_camera_unregister(struct gb_camera_module *module);
|
||||
|
||||
#endif /* __GB_CAMERA_H */
|
||||
|
|
@ -31,7 +31,7 @@ static ssize_t protocol_id_show(struct device *dev,
|
|||
{
|
||||
struct gbphy_device *gbphy_dev = to_gbphy_dev(dev);
|
||||
|
||||
return sprintf(buf, "0x%02x\n", gbphy_dev->cport_desc->protocol_id);
|
||||
return sysfs_emit(buf, "0x%02x\n", gbphy_dev->cport_desc->protocol_id);
|
||||
}
|
||||
static DEVICE_ATTR_RO(protocol_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -562,8 +562,7 @@ static int gb_loopback_async_sink(struct gb_loopback *gb, u32 len)
|
|||
return retval;
|
||||
}
|
||||
|
||||
static int gb_loopback_async_transfer_complete(
|
||||
struct gb_loopback_async_operation *op_async)
|
||||
static int gb_loopback_async_transfer_complete(struct gb_loopback_async_operation *op_async)
|
||||
{
|
||||
struct gb_loopback *gb;
|
||||
struct gb_operation *operation;
|
||||
|
|
@ -653,7 +652,8 @@ static int gb_loopback_request_handler(struct gb_operation *operation)
|
|||
}
|
||||
|
||||
if (!gb_operation_response_alloc(operation,
|
||||
len + sizeof(*response), GFP_KERNEL)) {
|
||||
len + sizeof(*response),
|
||||
GFP_KERNEL)) {
|
||||
dev_err(dev, "error allocating response\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -377,12 +377,8 @@ static void gb_power_supply_state_change(struct gb_power_supply *gbpsy,
|
|||
gbpsy->pm_acquired = true;
|
||||
} else {
|
||||
if (gbpsy->pm_acquired) {
|
||||
ret = gb_pm_runtime_put_autosuspend(connection->bundle);
|
||||
if (ret)
|
||||
dev_err(&connection->bundle->dev,
|
||||
"Fail to set wake unlock for none charging\n");
|
||||
else
|
||||
gbpsy->pm_acquired = false;
|
||||
gb_pm_runtime_put_autosuspend(connection->bundle);
|
||||
gbpsy->pm_acquired = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -160,7 +160,8 @@ static struct spi_transfer *get_next_xfer(struct spi_transfer *xfer,
|
|||
|
||||
/* Routines to transfer data */
|
||||
static struct gb_operation *gb_spi_operation_create(struct gb_spilib *spi,
|
||||
struct gb_connection *connection, struct spi_message *msg)
|
||||
struct gb_connection *connection,
|
||||
struct spi_message *msg)
|
||||
{
|
||||
struct gb_spi_transfer_request *request;
|
||||
struct spi_device *dev = msg->spi;
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ struct gb_tty {
|
|||
spinlock_t read_lock;
|
||||
spinlock_t write_lock;
|
||||
struct async_icount iocount;
|
||||
struct async_icount oldcount;
|
||||
wait_queue_head_t wioctl;
|
||||
struct mutex mutex;
|
||||
u8 ctrlin; /* input control lines */
|
||||
|
|
@ -318,7 +317,7 @@ static int gb_uart_wait_for_all_credits(struct gb_tty *gb_tty)
|
|||
return 0;
|
||||
|
||||
ret = wait_for_completion_timeout(&gb_tty->credits_complete,
|
||||
msecs_to_jiffies(GB_UART_CREDIT_WAIT_TIMEOUT_MSEC));
|
||||
msecs_to_jiffies(GB_UART_CREDIT_WAIT_TIMEOUT_MSEC));
|
||||
if (!ret) {
|
||||
dev_err(&gb_tty->gbphy_dev->dev,
|
||||
"time out waiting for credits\n");
|
||||
|
|
@ -643,11 +642,16 @@ static int wait_serial_change(struct gb_tty *gb_tty, unsigned long arg)
|
|||
if (!(arg & (TIOCM_DSR | TIOCM_RI | TIOCM_CD)))
|
||||
return -EINVAL;
|
||||
|
||||
do {
|
||||
spin_lock_irq(&gb_tty->read_lock);
|
||||
old = gb_tty->iocount;
|
||||
spin_unlock_irq(&gb_tty->read_lock);
|
||||
|
||||
add_wait_queue(&gb_tty->wioctl, &wait);
|
||||
for (;;) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
||||
spin_lock_irq(&gb_tty->read_lock);
|
||||
old = gb_tty->oldcount;
|
||||
new = gb_tty->iocount;
|
||||
gb_tty->oldcount = new;
|
||||
spin_unlock_irq(&gb_tty->read_lock);
|
||||
|
||||
if ((arg & TIOCM_DSR) && (old.dsr != new.dsr))
|
||||
|
|
@ -657,18 +661,20 @@ static int wait_serial_change(struct gb_tty *gb_tty, unsigned long arg)
|
|||
if ((arg & TIOCM_RI) && (old.rng != new.rng))
|
||||
break;
|
||||
|
||||
add_wait_queue(&gb_tty->wioctl, &wait);
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule();
|
||||
remove_wait_queue(&gb_tty->wioctl, &wait);
|
||||
if (gb_tty->disconnected) {
|
||||
if (arg & TIOCM_CD)
|
||||
break;
|
||||
retval = -ENODEV;
|
||||
} else if (signal_pending(current)) {
|
||||
retval = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
} while (!retval);
|
||||
|
||||
schedule();
|
||||
|
||||
if (signal_pending(current)) {
|
||||
retval = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
__set_current_state(TASK_RUNNING);
|
||||
remove_wait_queue(&gb_tty->wioctl, &wait);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ following components are available
|
|||
driver via the V4L subsystem.
|
||||
|
||||
4) Advanced Linux Sound Architecture (ALSA)
|
||||
Standard sound applications (e.g. aplay, arecord, audacity) can by
|
||||
Standard sound applications (e.g. aplay, arecord, audacity) can be
|
||||
used to access the driver via the ALSA subsystem.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -439,7 +439,6 @@ static int comp_register_videodev(struct most_video_dev *mdev)
|
|||
mdev->vdev->release = video_device_release;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static void comp_unregister_videodev(struct most_video_dev *mdev)
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ struct nvec_msg {
|
|||
/**
|
||||
* struct nvec_chip - A single connection to an NVIDIA Embedded controller
|
||||
* @dev: The device
|
||||
* @gpio: The same as for &struct nvec_platform_data
|
||||
* @gpiod: GPIO descriptor for the embedded controller request line
|
||||
* @irq: The IRQ of the I2C device
|
||||
* @i2c_addr: The address of the I2C slave
|
||||
* @base: The base of the memory mapped region of the I2C device
|
||||
|
|
|
|||
|
|
@ -481,7 +481,7 @@ netdev_tx_t cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
cvmx_fau_fetch_and_add32(FAU_TOTAL_TX_TO_CLEAN, 1);
|
||||
}
|
||||
|
||||
if (total_to_clean & 0x3ff) {
|
||||
if ((total_to_clean & 0x3ff) == 0) {
|
||||
/*
|
||||
* Schedule the cleanup tasklet every 1024 packets for
|
||||
* the pathological case of high traffic on one port
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
|
||||
#endif
|
||||
|
||||
/**
|
||||
/*
|
||||
* This is the definition of the Ethernet driver's private
|
||||
* driver state stored in netdev_priv(dev).
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ static int g_hwcursor = 1;
|
|||
static int g_noaccel __ro_after_init;
|
||||
static int g_nomtrr __ro_after_init;
|
||||
static const char *g_fbmode[] = {NULL, NULL};
|
||||
static const char *g_def_fbmode = "1024x768-32@60";
|
||||
static const char * const g_def_fbmode = "1024x768-32@60";
|
||||
static char *g_settings;
|
||||
static int g_dualview __ro_after_init;
|
||||
static char *g_option;
|
||||
|
|
@ -384,7 +384,7 @@ static inline unsigned int chan_to_field(unsigned int chan,
|
|||
return chan << bf->offset;
|
||||
}
|
||||
|
||||
static int __maybe_unused lynxfb_suspend(struct device *dev)
|
||||
static int lynxfb_suspend(struct device *dev)
|
||||
{
|
||||
struct fb_info *info;
|
||||
struct sm750_dev *sm750_dev;
|
||||
|
|
@ -405,7 +405,7 @@ static int __maybe_unused lynxfb_suspend(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused lynxfb_resume(struct device *dev)
|
||||
static int lynxfb_resume(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct fb_info *info;
|
||||
|
|
@ -479,7 +479,7 @@ static int lynxfb_ops_check_var(struct fb_var_screeninfo *var,
|
|||
|
||||
/* check if current fb's video memory big enough to hold the onscreen*/
|
||||
request = var->xres_virtual * (var->bits_per_pixel >> 3);
|
||||
/* defaulty crtc->channel go with par->index */
|
||||
/* default crtc->channel go with par->index */
|
||||
|
||||
request = ALIGN(request, crtc->line_pad);
|
||||
request = request * var->yres_virtual;
|
||||
|
|
@ -825,6 +825,11 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void lynxfb_unset_fbinfo(struct fb_info *info)
|
||||
{
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
}
|
||||
|
||||
/* chip specific g_option configuration routine */
|
||||
static void sm750fb_setup(struct sm750_dev *sm750_dev, char *src)
|
||||
{
|
||||
|
|
@ -910,6 +915,7 @@ static void sm750fb_framebuffer_release(struct sm750_dev *sm750_dev)
|
|||
while (sm750_dev->fb_count) {
|
||||
fb_info = sm750_dev->fbinfo[sm750_dev->fb_count - 1];
|
||||
unregister_framebuffer(fb_info);
|
||||
lynxfb_unset_fbinfo(fb_info);
|
||||
framebuffer_release(fb_info);
|
||||
sm750_dev->fb_count--;
|
||||
}
|
||||
|
|
@ -936,12 +942,14 @@ static int sm750fb_framebuffer_alloc(struct sm750_dev *sm750_dev, int fbidx)
|
|||
|
||||
err = register_framebuffer(fb_info);
|
||||
if (err < 0)
|
||||
goto release_fb;
|
||||
goto unset_fb;
|
||||
|
||||
sm750_dev->fb_count++;
|
||||
|
||||
return 0;
|
||||
|
||||
unset_fb:
|
||||
lynxfb_unset_fbinfo(fb_info);
|
||||
release_fb:
|
||||
framebuffer_release(fb_info);
|
||||
return err;
|
||||
|
|
@ -1094,14 +1102,14 @@ static const struct pci_device_id smi_pci_table[] = {
|
|||
|
||||
MODULE_DEVICE_TABLE(pci, smi_pci_table);
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(lynxfb_pm_ops, lynxfb_suspend, lynxfb_resume);
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(lynxfb_pm_ops, lynxfb_suspend, lynxfb_resume);
|
||||
|
||||
static struct pci_driver lynxfb_driver = {
|
||||
.name = "sm750fb",
|
||||
.id_table = smi_pci_table,
|
||||
.probe = lynxfb_pci_probe,
|
||||
.remove = lynxfb_pci_remove,
|
||||
.driver.pm = &lynxfb_pm_ops,
|
||||
.driver.pm = pm_sleep_ptr(&lynxfb_pm_ops),
|
||||
};
|
||||
|
||||
static int __init lynxfb_init(void)
|
||||
|
|
|
|||
|
|
@ -195,7 +195,8 @@ int sm750_hw_fillrect(struct lynx_accel *accel,
|
|||
u32 color, u32 rop);
|
||||
|
||||
/**
|
||||
* sm750_hm_copyarea
|
||||
* sm750_hw_copyarea
|
||||
* @accel: Acceleration device data
|
||||
* @source_base: Address of source: offset in frame buffer
|
||||
* @source_pitch: Pitch value of source surface in BYTE
|
||||
* @sx: Starting x coordinate of source surface
|
||||
|
|
@ -219,6 +220,7 @@ int sm750_hw_copyarea(struct lynx_accel *accel,
|
|||
|
||||
/**
|
||||
* sm750_hw_imageblit
|
||||
* @accel: Acceleration device data
|
||||
* @src_buf: pointer to start of source buffer in system memory
|
||||
* @start_bit: Mono data can start at any bit in a byte, this value should be
|
||||
*>----- 0 to 7
|
||||
|
|
|
|||
|
|
@ -298,9 +298,9 @@ struct vme_resource *vme_slave_request(struct vme_dev *vdev, u32 address,
|
|||
|
||||
err_alloc:
|
||||
/* Unlock image */
|
||||
mutex_lock(&slave_image->mtx);
|
||||
slave_image->locked = 0;
|
||||
mutex_unlock(&slave_image->mtx);
|
||||
mutex_lock(&allocated_image->mtx);
|
||||
allocated_image->locked = 0;
|
||||
mutex_unlock(&allocated_image->mtx);
|
||||
err_image:
|
||||
err_bus:
|
||||
return NULL;
|
||||
|
|
@ -495,9 +495,9 @@ struct vme_resource *vme_master_request(struct vme_dev *vdev, u32 address,
|
|||
|
||||
err_alloc:
|
||||
/* Unlock image */
|
||||
spin_lock(&master_image->lock);
|
||||
master_image->locked = 0;
|
||||
spin_unlock(&master_image->lock);
|
||||
spin_lock(&allocated_image->lock);
|
||||
allocated_image->locked = 0;
|
||||
spin_unlock(&allocated_image->lock);
|
||||
err_image:
|
||||
err_bus:
|
||||
return NULL;
|
||||
|
|
@ -865,9 +865,9 @@ struct vme_resource *vme_dma_request(struct vme_dev *vdev, u32 route)
|
|||
|
||||
err_alloc:
|
||||
/* Unlock image */
|
||||
mutex_lock(&dma_ctrlr->mtx);
|
||||
dma_ctrlr->locked = 0;
|
||||
mutex_unlock(&dma_ctrlr->mtx);
|
||||
mutex_lock(&allocated_ctrlr->mtx);
|
||||
allocated_ctrlr->locked = 0;
|
||||
mutex_unlock(&allocated_ctrlr->mtx);
|
||||
err_ctrlr:
|
||||
err_bus:
|
||||
return NULL;
|
||||
|
|
@ -1469,9 +1469,9 @@ struct vme_resource *vme_lm_request(struct vme_dev *vdev)
|
|||
|
||||
err_alloc:
|
||||
/* Unlock image */
|
||||
mutex_lock(&lm->mtx);
|
||||
lm->locked = 0;
|
||||
mutex_unlock(&lm->mtx);
|
||||
mutex_lock(&allocated_lm->mtx);
|
||||
allocated_lm->locked = 0;
|
||||
mutex_unlock(&allocated_lm->mtx);
|
||||
err_lm:
|
||||
err_bus:
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/byteorder/generic.h>
|
||||
#include <linux/string_choices.h>
|
||||
|
||||
#include "vme.h"
|
||||
#include "vme_bridge.h"
|
||||
|
|
@ -2458,7 +2459,7 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
geoid);
|
||||
|
||||
dev_info(&pdev->dev, "VME Write and flush and error check is %s\n",
|
||||
err_chk ? "enabled" : "disabled");
|
||||
str_enabled_disabled(err_chk));
|
||||
|
||||
retval = tsi148_crcsr_init(tsi148_bridge, pdev);
|
||||
if (retval) {
|
||||
|
|
|
|||
|
|
@ -59,14 +59,9 @@ static inline int gb_pm_runtime_get_sync(struct gb_bundle *bundle)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int gb_pm_runtime_put_autosuspend(struct gb_bundle *bundle)
|
||||
static inline void gb_pm_runtime_put_autosuspend(struct gb_bundle *bundle)
|
||||
{
|
||||
int retval;
|
||||
|
||||
pm_runtime_mark_last_busy(&bundle->dev);
|
||||
retval = pm_runtime_put_autosuspend(&bundle->dev);
|
||||
|
||||
return retval;
|
||||
pm_runtime_put_autosuspend(&bundle->dev);
|
||||
}
|
||||
|
||||
static inline void gb_pm_runtime_get_noresume(struct gb_bundle *bundle)
|
||||
|
|
@ -82,8 +77,7 @@ static inline void gb_pm_runtime_put_noidle(struct gb_bundle *bundle)
|
|||
#else
|
||||
static inline int gb_pm_runtime_get_sync(struct gb_bundle *bundle)
|
||||
{ return 0; }
|
||||
static inline int gb_pm_runtime_put_autosuspend(struct gb_bundle *bundle)
|
||||
{ return 0; }
|
||||
static inline void gb_pm_runtime_put_autosuspend(struct gb_bundle *bundle) {}
|
||||
|
||||
static inline void gb_pm_runtime_get_noresume(struct gb_bundle *bundle) {}
|
||||
static inline void gb_pm_runtime_put_noidle(struct gb_bundle *bundle) {}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user