Compare commits
21
Commits
670265a2ca
...
502a0ff21a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
502a0ff21a | ||
|
|
9359ba377c | ||
|
|
63f7efc319 | ||
|
|
08bd2cf2fd | ||
|
|
3e090e8a5a | ||
|
|
2aa5b04a01 | ||
|
|
5c7245e156 | ||
|
|
823de1bf0a | ||
|
|
9261922c66 | ||
|
|
6c42b74e14 | ||
|
|
cd75bcb1f9 | ||
|
|
36fa0b8913 | ||
|
|
dcea3dc03a | ||
|
|
dd36ee6907 | ||
|
|
cdd38f1012 | ||
|
|
f70d95850e | ||
|
|
4f8d7f167d | ||
|
|
965c9d231b | ||
|
|
2fcfbdae10 | ||
|
|
d3fd5a30ad | ||
|
|
91275a8004 |
No files matched your search
@@ -14,12 +14,11 @@ description:
|
||||
functionality. Along with it the user can enable the touchkey which can work
|
||||
as a basic HOME and BACK key for phones.
|
||||
|
||||
allOf:
|
||||
- $ref: touchscreen.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: st,stmfts
|
||||
enum:
|
||||
- st,stmfts
|
||||
- st,stmfts5
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
@@ -40,6 +39,14 @@ properties:
|
||||
vdd-supply:
|
||||
description: Power supply
|
||||
|
||||
mode-switch-gpios:
|
||||
description: Optional switch between touchscreen SLPI and AP mode.
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
description: Reset GPIO (active-low)
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
@@ -47,6 +54,17 @@ required:
|
||||
- interrupts
|
||||
- vdd-supply
|
||||
|
||||
allOf:
|
||||
- $ref: touchscreen.yaml#
|
||||
- if:
|
||||
not:
|
||||
properties:
|
||||
compatible:
|
||||
const: st,stmfts5
|
||||
then:
|
||||
properties:
|
||||
mode-switch-gpios: false
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
@@ -60,10 +78,9 @@ examples:
|
||||
touchscreen@49 {
|
||||
compatible = "st,stmfts";
|
||||
reg = <0x49>;
|
||||
interrupt-parent = <&gpa1>;
|
||||
interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
|
||||
touchscreen-size-x = <1599>;
|
||||
touchscreen-size-y = <2559>;
|
||||
interrupts-extended = <&gpa1 1 IRQ_TYPE_LEVEL_LOW>;
|
||||
touchscreen-size-x = <1600>;
|
||||
touchscreen-size-y = <2560>;
|
||||
touch-key-connected;
|
||||
avdd-supply = <&ldo30_reg>;
|
||||
vdd-supply = <&ldo31_reg>;
|
||||
|
||||
@@ -26,7 +26,24 @@
|
||||
|
||||
status = "okay";
|
||||
|
||||
/* ST,FTS @ 49 */
|
||||
touchscreen@49 {
|
||||
compatible = "st,stmfts5";
|
||||
reg = <0x49>;
|
||||
|
||||
pinctrl-0 = <&touchscreen_irq_n>, <&touchscreen_reset>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
interrupts-extended = <&tlmm 125 IRQ_TYPE_LEVEL_LOW>;
|
||||
|
||||
mode-switch-gpios = <&tlmm 136 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&tlmm 99 GPIO_ACTIVE_LOW>;
|
||||
|
||||
avdd-supply = <&vreg_l19a_3p3>;
|
||||
vdd-supply = <&vreg_l14a_1p8>;
|
||||
|
||||
touchscreen-size-x = <1080>;
|
||||
touchscreen-size-y = <2160>;
|
||||
};
|
||||
};
|
||||
|
||||
&mdss_dsi0 {
|
||||
|
||||
@@ -466,7 +466,7 @@
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
touchscreen_pins: ts-pins-gpio-state {
|
||||
touchscreen_irq_n: ts-irq-n-gpio-state {
|
||||
pins = "gpio125";
|
||||
function = "gpio";
|
||||
drive-strength = <2>;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2018 SwtcR <swtcr0@gmail.com>
|
||||
* Copyright (C) 2023-2024 Azkali <a.ffcc7@gmail.com>
|
||||
* Copyright (C) 2023-2026 Azkali <a.ffcc7@gmail.com>
|
||||
* Copyright (C) 2026 Thomas Makin <halorocker89@gmail.com>
|
||||
*
|
||||
* Based on Sharp ls043t1le01 panel driver by Werner Johansson <werner.johansson@sonymobile.com>
|
||||
*
|
||||
@@ -27,6 +28,7 @@
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_panel.h>
|
||||
#include <drm/drm_modes.h>
|
||||
@@ -110,6 +112,7 @@ struct nx_panel {
|
||||
bool enabled;
|
||||
|
||||
const struct drm_display_mode *mode;
|
||||
enum drm_panel_orientation orientation;
|
||||
|
||||
struct init_cmd *init_cmds;
|
||||
struct init_cmd *suspend_cmds;
|
||||
@@ -631,21 +634,32 @@ static int nx_panel_get_modes(struct drm_panel *panel,
|
||||
connector->display_info.height_mm = 137;
|
||||
connector->display_info.bpc = 8;
|
||||
|
||||
drm_connector_set_panel_orientation(connector, nx->orientation);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static enum drm_panel_orientation nx_panel_get_orientation(struct drm_panel *panel)
|
||||
{
|
||||
struct nx_panel *nx = to_nx_panel(panel);
|
||||
|
||||
return nx->orientation;
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs nx_panel_funcs = {
|
||||
.prepare = nx_panel_prepare,
|
||||
.unprepare = nx_panel_unprepare,
|
||||
.enable = nx_panel_enable,
|
||||
.disable = nx_panel_disable,
|
||||
.get_modes = nx_panel_get_modes,
|
||||
.get_orientation = nx_panel_get_orientation,
|
||||
};
|
||||
|
||||
static int nx_panel_add(struct nx_panel *nx)
|
||||
{
|
||||
struct device *dev = &nx->dsi->dev;
|
||||
struct device_node *np;
|
||||
int ret;
|
||||
|
||||
nx->mode = &default_mode;
|
||||
|
||||
@@ -677,6 +691,12 @@ static int nx_panel_add(struct nx_panel *nx)
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
ret = of_drm_get_panel_orientation(dev->of_node, &nx->orientation);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to get orientation %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
drm_panel_init(&nx->base, &nx->dsi->dev, &nx_panel_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
|
||||
|
||||
@@ -304,7 +304,7 @@ static int seesaw_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id seesaw_id_table[] = {
|
||||
{ SEESAW_DEVICE_NAME },
|
||||
{ .name = SEESAW_DEVICE_NAME },
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, seesaw_id_table);
|
||||
|
||||
@@ -337,7 +337,7 @@ static void as5011_remove(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id as5011_id[] = {
|
||||
{ MODULE_DEVICE_ALIAS },
|
||||
{ .name = MODULE_DEVICE_ALIAS },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, as5011_id);
|
||||
|
||||
@@ -126,7 +126,7 @@ MODULE_DEVICE_TABLE(of, of_qwiic_match);
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
static const struct i2c_device_id qwiic_id_table[] = {
|
||||
{ KBUILD_MODNAME },
|
||||
{ .name = KBUILD_MODNAME },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, qwiic_id_table);
|
||||
|
||||
@@ -842,8 +842,8 @@ static int adp5588_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(adp5588_dev_pm_ops, adp5588_suspend, adp5588_resume);
|
||||
|
||||
static const struct i2c_device_id adp5588_id[] = {
|
||||
{ "adp5588-keys" },
|
||||
{ "adp5587-keys" },
|
||||
{ .name = "adp5588-keys" },
|
||||
{ .name = "adp5587-keys" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, adp5588_id);
|
||||
|
||||
@@ -651,13 +651,13 @@ static const struct of_device_id cap11xx_dt_ids[] = {
|
||||
MODULE_DEVICE_TABLE(of, cap11xx_dt_ids);
|
||||
|
||||
static const struct i2c_device_id cap11xx_i2c_ids[] = {
|
||||
{ "cap1106", (kernel_ulong_t)&cap1106_model },
|
||||
{ "cap1126", (kernel_ulong_t)&cap1126_model },
|
||||
{ "cap1188", (kernel_ulong_t)&cap1188_model },
|
||||
{ "cap1203", (kernel_ulong_t)&cap1203_model },
|
||||
{ "cap1206", (kernel_ulong_t)&cap1206_model },
|
||||
{ "cap1293", (kernel_ulong_t)&cap1293_model },
|
||||
{ "cap1298", (kernel_ulong_t)&cap1298_model },
|
||||
{ .name = "cap1106", .driver_data = (kernel_ulong_t)&cap1106_model },
|
||||
{ .name = "cap1126", .driver_data = (kernel_ulong_t)&cap1126_model },
|
||||
{ .name = "cap1188", .driver_data = (kernel_ulong_t)&cap1188_model },
|
||||
{ .name = "cap1203", .driver_data = (kernel_ulong_t)&cap1203_model },
|
||||
{ .name = "cap1206", .driver_data = (kernel_ulong_t)&cap1206_model },
|
||||
{ .name = "cap1293", .driver_data = (kernel_ulong_t)&cap1293_model },
|
||||
{ .name = "cap1298", .driver_data = (kernel_ulong_t)&cap1298_model },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, cap11xx_i2c_ids);
|
||||
|
||||
@@ -209,7 +209,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(cypress_sf_pm_ops,
|
||||
cypress_sf_suspend, cypress_sf_resume);
|
||||
|
||||
static const struct i2c_device_id cypress_sf_id_table[] = {
|
||||
{ CYPRESS_SF_DEV_NAME },
|
||||
{ .name = CYPRESS_SF_DEV_NAME },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, cypress_sf_id_table);
|
||||
|
||||
@@ -128,7 +128,7 @@ static int dir685_tk_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id dir685_tk_id[] = {
|
||||
{ "dir685tk" },
|
||||
{ .name = "dir685tk" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, dir685_tk_id);
|
||||
|
||||
@@ -788,7 +788,7 @@ static int lm8323_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(lm8323_pm_ops, lm8323_suspend, lm8323_resume);
|
||||
|
||||
static const struct i2c_device_id lm8323_id[] = {
|
||||
{ "lm8323" },
|
||||
{ .name = "lm8323" },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
@@ -194,7 +194,7 @@ static int lm8333_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id lm8333_id[] = {
|
||||
{ "lm8333" },
|
||||
{ .name = "lm8333" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, lm8333_id);
|
||||
|
||||
@@ -270,7 +270,7 @@ static int max7359_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(max7359_pm, max7359_suspend, max7359_resume);
|
||||
|
||||
static const struct i2c_device_id max7359_ids[] = {
|
||||
{ "max7359" },
|
||||
{ .name = "max7359" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, max7359_ids);
|
||||
|
||||
@@ -322,7 +322,7 @@ static int mpr_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(mpr121_touchkey_pm_ops, mpr_suspend, mpr_resume);
|
||||
|
||||
static const struct i2c_device_id mpr121_id[] = {
|
||||
{ "mpr121_touchkey" },
|
||||
{ .name = "mpr121_touchkey" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, mpr121_id);
|
||||
|
||||
@@ -233,7 +233,7 @@ static int qt1070_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(qt1070_pm_ops, qt1070_suspend, qt1070_resume);
|
||||
|
||||
static const struct i2c_device_id qt1070_id[] = {
|
||||
{ "qt1070" },
|
||||
{ .name = "qt1070" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, qt1070_id);
|
||||
|
||||
@@ -393,7 +393,7 @@ static int qt2160_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id qt2160_idtable[] = {
|
||||
{ "qt2160" },
|
||||
{ .name = "qt2160" },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
@@ -354,7 +354,7 @@ static int tca8418_keypad_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id tca8418_id[] = {
|
||||
{ "tca8418", 8418, },
|
||||
{ .name = "tca8418", .driver_data = 8418 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, tca8418_id);
|
||||
|
||||
@@ -326,7 +326,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(tm2_touchkey_pm_ops,
|
||||
tm2_touchkey_suspend, tm2_touchkey_resume);
|
||||
|
||||
static const struct i2c_device_id tm2_touchkey_id_table[] = {
|
||||
{ TM2_TOUCHKEY_DEV_NAME },
|
||||
{ .name = TM2_TOUCHKEY_DEV_NAME },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, tm2_touchkey_id_table);
|
||||
|
||||
@@ -282,6 +282,13 @@ config INPUT_MAX77693_HAPTIC
|
||||
To compile this driver as module, choose M here: the
|
||||
module will be called max77693-haptic.
|
||||
|
||||
config INPUT_MAX77620_ONOFF
|
||||
tristate "MAX77620 ONOFF support"
|
||||
depends on MFD_MAX77620
|
||||
help
|
||||
Support the ONOFF block of MAX77620 PMICs as an input device
|
||||
reporting power button status.
|
||||
|
||||
config INPUT_MAX8925_ONKEY
|
||||
tristate "MAX8925 ONKEY support"
|
||||
depends on MFD_MAX8925
|
||||
|
||||
@@ -55,6 +55,7 @@ obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o
|
||||
obj-$(CONFIG_INPUT_MAX7360_ROTARY) += max7360-rotary.o
|
||||
obj-$(CONFIG_INPUT_MAX77650_ONKEY) += max77650-onkey.o
|
||||
obj-$(CONFIG_INPUT_MAX77693_HAPTIC) += max77693-haptic.o
|
||||
obj-$(CONFIG_INPUT_MAX77620_ONOFF) += max77620-onoff.o
|
||||
obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o
|
||||
obj-$(CONFIG_INPUT_MAX8997_HAPTIC) += max8997_haptic.o
|
||||
obj-$(CONFIG_INPUT_MC13783_PWRBUTTON) += mc13783-pwrbutton.o
|
||||
|
||||
@@ -72,11 +72,11 @@ static int ad714x_i2c_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id ad714x_id[] = {
|
||||
{ "ad7142_captouch" },
|
||||
{ "ad7143_captouch" },
|
||||
{ "ad7147_captouch" },
|
||||
{ "ad7147a_captouch" },
|
||||
{ "ad7148_captouch" },
|
||||
{ .name = "ad7142_captouch" },
|
||||
{ .name = "ad7143_captouch" },
|
||||
{ .name = "ad7147_captouch" },
|
||||
{ .name = "ad7147a_captouch" },
|
||||
{ .name = "ad7148_captouch" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ad714x_id);
|
||||
|
||||
@@ -96,7 +96,7 @@ static int adxl34x_i2c_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id adxl34x_id[] = {
|
||||
{ "adxl34x" },
|
||||
{ .name = "adxl34x" },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
@@ -192,7 +192,7 @@ static void apanel_shutdown(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id apanel_id[] = {
|
||||
{ "fujitsu_apanel" },
|
||||
{ .name = "fujitsu_apanel" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, apanel_id);
|
||||
|
||||
@@ -257,7 +257,7 @@ static const struct of_device_id atmel_captouch_of_id[] = {
|
||||
MODULE_DEVICE_TABLE(of, atmel_captouch_of_id);
|
||||
|
||||
static const struct i2c_device_id atmel_captouch_id[] = {
|
||||
{ "atmel_captouch" },
|
||||
{ .name = "atmel_captouch" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, atmel_captouch_id);
|
||||
|
||||
@@ -536,9 +536,9 @@ static int __maybe_unused bma150_resume(struct device *dev)
|
||||
static UNIVERSAL_DEV_PM_OPS(bma150_pm, bma150_suspend, bma150_resume, NULL);
|
||||
|
||||
static const struct i2c_device_id bma150_id[] = {
|
||||
{ "bma150" },
|
||||
{ "smb380" },
|
||||
{ "bma023" },
|
||||
{ .name = "bma150" },
|
||||
{ .name = "smb380" },
|
||||
{ .name = "bma023" },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ static const struct dev_pm_ops cma3000_i2c_pm_ops = {
|
||||
};
|
||||
|
||||
static const struct i2c_device_id cma3000_i2c_id[] = {
|
||||
{ "cma3000_d01" },
|
||||
{ .name = "cma3000_d01" },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
@@ -1305,7 +1305,7 @@ MODULE_DEVICE_TABLE(of, da7280_of_match);
|
||||
#endif
|
||||
|
||||
static const struct i2c_device_id da7280_i2c_id[] = {
|
||||
{ "da7280", },
|
||||
{ .name = "da7280" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, da7280_i2c_id);
|
||||
|
||||
@@ -630,10 +630,10 @@ static int drv260x_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(drv260x_pm_ops, drv260x_suspend, drv260x_resume);
|
||||
|
||||
static const struct i2c_device_id drv260x_id[] = {
|
||||
{ "drv2604" },
|
||||
{ "drv2604l" },
|
||||
{ "drv2605" },
|
||||
{ "drv2605l" },
|
||||
{ .name = "drv2604" },
|
||||
{ .name = "drv2604l" },
|
||||
{ .name = "drv2605" },
|
||||
{ .name = "drv2605l" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, drv260x_id);
|
||||
|
||||
@@ -281,7 +281,7 @@ static int drv2665_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(drv2665_pm_ops, drv2665_suspend, drv2665_resume);
|
||||
|
||||
static const struct i2c_device_id drv2665_id[] = {
|
||||
{ "drv2665" },
|
||||
{ .name = "drv2665" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, drv2665_id);
|
||||
|
||||
@@ -458,7 +458,7 @@ static int drv2667_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(drv2667_pm_ops, drv2667_suspend, drv2667_resume);
|
||||
|
||||
static const struct i2c_device_id drv2667_id[] = {
|
||||
{ "drv2667" },
|
||||
{ .name = "drv2667" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, drv2667_id);
|
||||
|
||||
@@ -525,7 +525,7 @@ static int kxtj9_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(kxtj9_pm_ops, kxtj9_suspend, kxtj9_resume);
|
||||
|
||||
static const struct i2c_device_id kxtj9_id[] = {
|
||||
{ NAME },
|
||||
{ .name = NAME },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2018 Billy Laws
|
||||
* Copyright (C) 2020-2022 CTCaer
|
||||
*
|
||||
* Author:
|
||||
* Billy Laws <blaws05@gmail.com>
|
||||
* CTCaer <ctcaer@gmail.com>
|
||||
*
|
||||
* Description:
|
||||
* ONOFF driver for MAXIM 77620 charger/power-supply.
|
||||
*/
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mfd/max77620.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#define ONOFF_IRQF 2
|
||||
#define ONOFF_IRQR 3
|
||||
|
||||
/* MAX77620 IRQ ONOFF interrupts */
|
||||
#define MAX77620_IRQ_ONOFF_MRWRN 0
|
||||
#define MAX77620_IRQ_ONOFF_EN0_1SEC 1
|
||||
#define MAX77620_IRQ_ONOFF_EN0_F 2
|
||||
#define MAX77620_IRQ_ONOFF_EN0_R 3
|
||||
#define MAX77620_IRQ_ONOFF_LID_F 4
|
||||
#define MAX77620_IRQ_ONOFF_LID_R 5
|
||||
#define MAX77620_IRQ_ONOFF_ACOK_F 6
|
||||
#define MAX77620_IRQ_ONOFF_ACOK_R 7
|
||||
|
||||
struct max77620_onoff {
|
||||
struct regmap *rmap;
|
||||
struct input_dev *input;
|
||||
int irq_f, irq_r;
|
||||
unsigned int code;
|
||||
bool suspended;
|
||||
};
|
||||
|
||||
static const struct regmap_irq max77620_onoff_irqs[] = {
|
||||
REGMAP_IRQ_REG(MAX77620_IRQ_ONOFF_MRWRN, 0, MAX77620_IRQ_ONOFF_MRWRN_MASK),
|
||||
REGMAP_IRQ_REG(MAX77620_IRQ_ONOFF_EN0_1SEC, 0, MAX77620_IRQ_ONOFF_EN0_1SEC_MASK),
|
||||
REGMAP_IRQ_REG(MAX77620_IRQ_ONOFF_EN0_F, 0, MAX77620_IRQ_ONOFF_EN0_F_MASK),
|
||||
REGMAP_IRQ_REG(MAX77620_IRQ_ONOFF_EN0_R, 0, MAX77620_IRQ_ONOFF_EN0_R_MASK),
|
||||
REGMAP_IRQ_REG(MAX77620_IRQ_ONOFF_LID_F, 0, MAX77620_IRQ_ONOFF_LID_F_MASK),
|
||||
REGMAP_IRQ_REG(MAX77620_IRQ_ONOFF_LID_R, 0, MAX77620_IRQ_ONOFF_LID_R_MASK),
|
||||
REGMAP_IRQ_REG(MAX77620_IRQ_ONOFF_ACOK_F, 0, MAX77620_IRQ_ONOFF_ACOK_F_MASK),
|
||||
REGMAP_IRQ_REG(MAX77620_IRQ_ONOFF_ACOK_R, 0, MAX77620_IRQ_ONOFF_ACOK_R_MASK),
|
||||
};
|
||||
|
||||
static struct regmap_irq_chip max77620_onoff_irq_chip = {
|
||||
.name = "max77620-onoff",
|
||||
.irqs = max77620_onoff_irqs,
|
||||
.num_irqs = ARRAY_SIZE(max77620_onoff_irqs),
|
||||
.num_regs = 1,
|
||||
.irq_reg_stride = 1,
|
||||
.status_base = MAX77620_REG_ONOFFIRQ,
|
||||
.mask_base = MAX77620_REG_ONOFFIRQM,
|
||||
};
|
||||
|
||||
static irqreturn_t max77620_onoff_handler(int irq, void *data)
|
||||
{
|
||||
struct max77620_onoff *onoff = data;
|
||||
bool pressed = irq == onoff->irq_r;
|
||||
|
||||
/* Skip release report in suspended state */
|
||||
if (onoff->suspended && !pressed)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
input_report_key(onoff->input, onoff->code, pressed);
|
||||
input_sync(onoff->input);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int max77620_onoff_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct max77620_onoff *onoff;
|
||||
struct device *dev, *parent;
|
||||
struct max77620_chip *chip = dev_get_drvdata(pdev->dev.parent);
|
||||
struct device_node *np;
|
||||
unsigned int code;
|
||||
int irq, ret;
|
||||
|
||||
dev = &pdev->dev;
|
||||
parent = dev->parent;
|
||||
|
||||
onoff = devm_kzalloc(dev, sizeof(*onoff), GFP_KERNEL);
|
||||
if (!onoff)
|
||||
return -ENOMEM;
|
||||
|
||||
onoff->rmap = chip->rmap;
|
||||
|
||||
ret = regmap_read(onoff->rmap, MAX77620_REG_ONOFFIRQ, &code);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "Failed to clear onoff irq: %d\n", ret);
|
||||
|
||||
np = of_get_child_by_name(pdev->dev.parent->of_node, "onoff");
|
||||
if (np && !of_device_is_available(np))
|
||||
np = NULL;
|
||||
|
||||
if (np)
|
||||
ret = of_property_read_u32(np, "maxim,onoff-keycode",
|
||||
&code);
|
||||
if (!np || ret < 0)
|
||||
onoff->code = KEY_POWER;
|
||||
else
|
||||
onoff->code = code;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
onoff->input = devm_input_allocate_device(dev);
|
||||
if (!onoff->input)
|
||||
return -ENOMEM;
|
||||
|
||||
onoff->input->name = "max77620_onoff";
|
||||
onoff->input->phys = "max77620_onoff/input0";
|
||||
onoff->input->id.bustype = BUS_I2C;
|
||||
input_set_capability(onoff->input, EV_KEY, onoff->code);
|
||||
|
||||
ret = devm_regmap_add_irq_chip(&pdev->dev, onoff->rmap, irq,
|
||||
IRQF_ONESHOT, -1,
|
||||
&max77620_onoff_irq_chip,
|
||||
&chip->onoff_irq_data);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to add onoff irq_chip %d\n", ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
onoff->irq_r = regmap_irq_get_virq(chip->onoff_irq_data,
|
||||
MAX77620_IRQ_ONOFF_EN0_R);
|
||||
onoff->irq_f = regmap_irq_get_virq(chip->onoff_irq_data,
|
||||
MAX77620_IRQ_ONOFF_EN0_F);
|
||||
|
||||
ret = devm_request_any_context_irq(dev, onoff->irq_r,
|
||||
max77620_onoff_handler,
|
||||
IRQF_ONESHOT, "en0-down", onoff);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
ret = devm_request_any_context_irq(dev, onoff->irq_f,
|
||||
max77620_onoff_handler,
|
||||
IRQF_ONESHOT, "en0-up", onoff);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
platform_set_drvdata(pdev, onoff);
|
||||
input_set_drvdata(onoff->input, onoff);
|
||||
device_init_wakeup(dev, 1);
|
||||
|
||||
ret = input_register_device(onoff->input);
|
||||
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
||||
static int max77620_onoff_suspend(struct device *dev)
|
||||
{
|
||||
struct max77620_onoff *onoff = dev_get_drvdata(dev);
|
||||
|
||||
onoff->suspended = true;
|
||||
|
||||
if (device_may_wakeup(dev))
|
||||
return enable_irq_wake(onoff->irq_f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max77620_onoff_resume(struct device *dev)
|
||||
{
|
||||
struct max77620_onoff *onoff = dev_get_drvdata(dev);
|
||||
unsigned int val, ret;
|
||||
|
||||
/* Clear ON/OFF interrupts */
|
||||
ret = regmap_read(onoff->rmap, MAX77620_REG_ONOFFIRQ, &val);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "Failed to clear onoff irq: %d\n", ret);
|
||||
|
||||
onoff->suspended = false;
|
||||
|
||||
/* If ON/OFF was pressed, report it */
|
||||
if (val & MAX77620_IRQ_ONOFF_EN0_R_MASK) {
|
||||
input_report_key(onoff->input, onoff->code, 1);
|
||||
input_sync(onoff->input);
|
||||
}
|
||||
|
||||
/* Unconditionally release after resume */
|
||||
input_report_key(onoff->input, onoff->code, 0);
|
||||
input_sync(onoff->input);
|
||||
|
||||
if (device_may_wakeup(dev))
|
||||
return disable_irq_wake(onoff->irq_f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops max77620_onoff_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(max77620_onoff_suspend,
|
||||
max77620_onoff_resume)
|
||||
};
|
||||
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
static struct platform_driver max77620_onoff_driver = {
|
||||
.driver = {
|
||||
.name = "max77620-onoff",
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
.pm = &max77620_onoff_pm_ops,
|
||||
#endif
|
||||
},
|
||||
.probe = max77620_onoff_probe,
|
||||
};
|
||||
|
||||
static int __init max77620_onoff_init(void)
|
||||
{
|
||||
return platform_driver_register(&max77620_onoff_driver);
|
||||
}
|
||||
subsys_initcall(max77620_onoff_init);
|
||||
|
||||
static void __exit max77620_onoff_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&max77620_onoff_driver);
|
||||
}
|
||||
module_exit(max77620_onoff_exit);
|
||||
|
||||
MODULE_DESCRIPTION("MAXIM 77620 ONOFF driver");
|
||||
MODULE_AUTHOR("Billy Laws <blaws05@gmail.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
@@ -200,7 +200,7 @@ static int mma8450_probe(struct i2c_client *c)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id mma8450_id[] = {
|
||||
{ MMA8450_DRV_NAME },
|
||||
{ .name = MMA8450_DRV_NAME },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, mma8450_id);
|
||||
|
||||
@@ -189,7 +189,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(pcf8574_kp_pm_ops,
|
||||
pcf8574_kp_suspend, pcf8574_kp_resume);
|
||||
|
||||
static const struct i2c_device_id pcf8574_kp_id[] = {
|
||||
{ DRV_NAME },
|
||||
{ .name = DRV_NAME },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, pcf8574_kp_id);
|
||||
|
||||
@@ -1456,7 +1456,7 @@ static const struct dev_pm_ops cyapa_pm_ops = {
|
||||
};
|
||||
|
||||
static const struct i2c_device_id cyapa_id_table[] = {
|
||||
{ "cyapa" },
|
||||
{ .name = "cyapa" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, cyapa_id_table);
|
||||
|
||||
@@ -1407,7 +1407,7 @@ err:
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(elan_pm_ops, elan_suspend, elan_resume);
|
||||
|
||||
static const struct i2c_device_id elan_id[] = {
|
||||
{ DRIVER_NAME },
|
||||
{ .name = DRIVER_NAME },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, elan_id);
|
||||
|
||||
@@ -607,7 +607,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(synaptics_i2c_pm, synaptics_i2c_suspend,
|
||||
synaptics_i2c_resume);
|
||||
|
||||
static const struct i2c_device_id synaptics_i2c_id_table[] = {
|
||||
{ "synaptics_i2c" },
|
||||
{ .name = "synaptics_i2c" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, synaptics_i2c_id_table);
|
||||
|
||||
@@ -365,7 +365,7 @@ static const struct dev_pm_ops rmi_i2c_pm = {
|
||||
};
|
||||
|
||||
static const struct i2c_device_id rmi_id[] = {
|
||||
{ "rmi4_i2c" },
|
||||
{ .name = "rmi4_i2c" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, rmi_id);
|
||||
|
||||
@@ -413,7 +413,7 @@ static const struct dev_pm_ops rmi_smb_pm = {
|
||||
};
|
||||
|
||||
static const struct i2c_device_id rmi_id[] = {
|
||||
{ "rmi4_smbus" },
|
||||
{ .name = "rmi4_smbus" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, rmi_id);
|
||||
|
||||
@@ -42,8 +42,8 @@ static int ad7879_i2c_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id ad7879_id[] = {
|
||||
{ "ad7879" },
|
||||
{ "ad7889" },
|
||||
{ .name = "ad7879" },
|
||||
{ .name = "ad7889" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ad7879_id);
|
||||
|
||||
@@ -164,7 +164,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(ar1021_i2c_pm,
|
||||
ar1021_i2c_suspend, ar1021_i2c_resume);
|
||||
|
||||
static const struct i2c_device_id ar1021_i2c_id[] = {
|
||||
{ "ar1021" },
|
||||
{ .name = "ar1021" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ar1021_i2c_id);
|
||||
|
||||
@@ -3420,11 +3420,11 @@ MODULE_DEVICE_TABLE(acpi, mxt_acpi_id);
|
||||
#endif
|
||||
|
||||
static const struct i2c_device_id mxt_id[] = {
|
||||
{ "qt602240_ts" },
|
||||
{ "atmel_mxt_ts" },
|
||||
{ "atmel_mxt_tp" },
|
||||
{ "maxtouch" },
|
||||
{ "mXT224" },
|
||||
{ .name = "qt602240_ts" },
|
||||
{ .name = "atmel_mxt_ts" },
|
||||
{ .name = "atmel_mxt_tp" },
|
||||
{ .name = "maxtouch" },
|
||||
{ .name = "mXT224" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, mxt_id);
|
||||
|
||||
@@ -618,7 +618,7 @@ static int auo_pixcir_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id auo_pixcir_idtable[] = {
|
||||
{ "auo_pixcir_ts" },
|
||||
{ .name = "auo_pixcir_ts" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, auo_pixcir_idtable);
|
||||
|
||||
@@ -597,7 +597,7 @@ static int bu21013_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(bu21013_dev_pm_ops, bu21013_suspend, bu21013_resume);
|
||||
|
||||
static const struct i2c_device_id bu21013_id[] = {
|
||||
{ DRIVER_TP },
|
||||
{ .name = DRIVER_TP },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, bu21013_id);
|
||||
|
||||
@@ -442,7 +442,7 @@ static int bu21029_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(bu21029_pm_ops, bu21029_suspend, bu21029_resume);
|
||||
|
||||
static const struct i2c_device_id bu21029_ids[] = {
|
||||
{ DRIVER_NAME },
|
||||
{ .name = DRIVER_NAME },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, bu21029_ids);
|
||||
|
||||
@@ -322,7 +322,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(cy8ctma140_pm,
|
||||
cy8ctma140_suspend, cy8ctma140_resume);
|
||||
|
||||
static const struct i2c_device_id cy8ctma140_idtable[] = {
|
||||
{ CY8CTMA140_NAME },
|
||||
{ .name = CY8CTMA140_NAME },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, cy8ctma140_idtable);
|
||||
|
||||
@@ -267,7 +267,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(cy8ctmg110_pm,
|
||||
cy8ctmg110_suspend, cy8ctmg110_resume);
|
||||
|
||||
static const struct i2c_device_id cy8ctmg110_idtable[] = {
|
||||
{ CY8CTMG110_DRIVER_NAME, 1 },
|
||||
{ .name = CY8CTMG110_DRIVER_NAME, .driver_data = 1 },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
@@ -938,7 +938,7 @@ static const struct of_device_id cyttsp5_of_match[] = {
|
||||
MODULE_DEVICE_TABLE(of, cyttsp5_of_match);
|
||||
|
||||
static const struct i2c_device_id cyttsp5_i2c_id[] = {
|
||||
{ CYTTSP5_NAME },
|
||||
{ .name = CYTTSP5_NAME },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, cyttsp5_i2c_id);
|
||||
|
||||
@@ -103,7 +103,7 @@ static int cyttsp_i2c_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id cyttsp_i2c_id[] = {
|
||||
{ CY_I2C_NAME },
|
||||
{ .name = CY_I2C_NAME },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, cyttsp_i2c_id);
|
||||
|
||||
@@ -266,7 +266,7 @@ static int eeti_ts_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(eeti_ts_pm, eeti_ts_suspend, eeti_ts_resume);
|
||||
|
||||
static const struct i2c_device_id eeti_ts_id[] = {
|
||||
{ "eeti_ts" },
|
||||
{ .name = "eeti_ts" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, eeti_ts_id);
|
||||
|
||||
@@ -219,7 +219,7 @@ static int egalax_ts_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id egalax_ts_id[] = {
|
||||
{ "egalax_ts" },
|
||||
{ .name = "egalax_ts" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, egalax_ts_id);
|
||||
|
||||
@@ -1615,9 +1615,9 @@ static DEFINE_SIMPLE_DEV_PM_OPS(elants_i2c_pm_ops,
|
||||
elants_i2c_suspend, elants_i2c_resume);
|
||||
|
||||
static const struct i2c_device_id elants_i2c_id[] = {
|
||||
{ DEVICE_NAME, EKTH3500 },
|
||||
{ "ekth3500", EKTH3500 },
|
||||
{ "ektf3624", EKTF3624 },
|
||||
{ .name = DEVICE_NAME, .driver_data = EKTH3500 },
|
||||
{ .name = "ekth3500", .driver_data = EKTH3500 },
|
||||
{ .name = "ektf3624", .driver_data = EKTF3624 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, elants_i2c_id);
|
||||
|
||||
@@ -432,10 +432,10 @@ static int exc3000_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id exc3000_id[] = {
|
||||
{ "exc3000", EETI_EXC3000 },
|
||||
{ "exc80h60", EETI_EXC80H60 },
|
||||
{ "exc80h84", EETI_EXC80H84 },
|
||||
{ "exc81w32", EETI_EXC81W32 },
|
||||
{ .name = "exc3000", .driver_data = EETI_EXC3000 },
|
||||
{ .name = "exc80h60", .driver_data = EETI_EXC80H60 },
|
||||
{ .name = "exc80h84", .driver_data = EETI_EXC80H84 },
|
||||
{ .name = "exc81w32", .driver_data = EETI_EXC81W32 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, exc3000_id);
|
||||
|
||||
@@ -1523,7 +1523,7 @@ static int goodix_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(goodix_pm_ops, goodix_suspend, goodix_resume);
|
||||
|
||||
static const struct i2c_device_id goodix_ts_id[] = {
|
||||
{ "GDIX1001:00" },
|
||||
{ .name = "GDIX1001:00" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, goodix_ts_id);
|
||||
|
||||
@@ -1081,7 +1081,7 @@ static int hideep_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id hideep_i2c_id[] = {
|
||||
{ HIDEEP_I2C_NAME },
|
||||
{ .name = HIDEEP_I2C_NAME },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, hideep_i2c_id);
|
||||
|
||||
@@ -406,8 +406,8 @@ static const struct himax_chip hx83112b_chip = {
|
||||
};
|
||||
|
||||
static const struct i2c_device_id himax_ts_id[] = {
|
||||
{ "hx83100a", (kernel_ulong_t)&hx83100a_chip },
|
||||
{ "hx83112b", (kernel_ulong_t)&hx83112b_chip },
|
||||
{ .name = "hx83100a", .driver_data = (kernel_ulong_t)&hx83100a_chip },
|
||||
{ .name = "hx83112b", .driver_data = (kernel_ulong_t)&hx83112b_chip },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, himax_ts_id);
|
||||
|
||||
@@ -226,7 +226,7 @@ static int cst816x_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id cst816x_id[] = {
|
||||
{ .name = "cst816s", 0 },
|
||||
{ .name = "cst816s" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, cst816x_id);
|
||||
|
||||
@@ -1049,10 +1049,10 @@ static int ili210x_i2c_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id ili210x_i2c_id[] = {
|
||||
{ "ili210x", (long)&ili210x_chip },
|
||||
{ "ili2117", (long)&ili211x_chip },
|
||||
{ "ili2120", (long)&ili212x_chip },
|
||||
{ "ili251x", (long)&ili251x_chip },
|
||||
{ .name = "ili210x", .driver_data = (long)&ili210x_chip },
|
||||
{ .name = "ili2117", .driver_data = (long)&ili211x_chip },
|
||||
{ .name = "ili2120", .driver_data = (long)&ili212x_chip },
|
||||
{ .name = "ili251x", .driver_data = (long)&ili251x_chip },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id);
|
||||
|
||||
@@ -639,7 +639,7 @@ static int ilitek_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(ilitek_pm_ops, ilitek_suspend, ilitek_resume);
|
||||
|
||||
static const struct i2c_device_id ilitek_ts_i2c_id[] = {
|
||||
{ ILITEK_TS_NAME },
|
||||
{ .name = ILITEK_TS_NAME },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ilitek_ts_i2c_id);
|
||||
|
||||
@@ -213,7 +213,7 @@ static int max11801_ts_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id max11801_ts_id[] = {
|
||||
{ "max11801" },
|
||||
{ .name = "max11801" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, max11801_ts_id);
|
||||
|
||||
@@ -1536,7 +1536,7 @@ MODULE_DEVICE_TABLE(acpi, mip4_acpi_match);
|
||||
#endif
|
||||
|
||||
static const struct i2c_device_id mip4_i2c_ids[] = {
|
||||
{ MIP4_DEVICE_NAME },
|
||||
{ .name = MIP4_DEVICE_NAME },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, mip4_i2c_ids);
|
||||
|
||||
@@ -211,7 +211,7 @@ static int migor_ts_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(migor_ts_pm, migor_ts_suspend, migor_ts_resume);
|
||||
|
||||
static const struct i2c_device_id migor_ts_id[] = {
|
||||
{ "migor_ts" },
|
||||
{ .name = "migor_ts" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, migor_ts_id);
|
||||
|
||||
@@ -667,7 +667,7 @@ static int mms114_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(mms114_pm_ops, mms114_suspend, mms114_resume);
|
||||
|
||||
static const struct i2c_device_id mms114_id[] = {
|
||||
{ "mms114" },
|
||||
{ .name = "mms114" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, mms114_id);
|
||||
|
||||
@@ -326,8 +326,8 @@ static const struct of_device_id nvt_ts_of_match[] = {
|
||||
MODULE_DEVICE_TABLE(of, nvt_ts_of_match);
|
||||
|
||||
static const struct i2c_device_id nvt_ts_i2c_id[] = {
|
||||
{ "nt11205-ts", (unsigned long) &nvt_nt11205_ts_data },
|
||||
{ "nt36672a-ts", (unsigned long) &nvt_nt36672a_ts_data },
|
||||
{ .name = "nt11205-ts", .driver_data = (unsigned long)&nvt_nt11205_ts_data },
|
||||
{ .name = "nt36672a-ts", .driver_data = (unsigned long)&nvt_nt36672a_ts_data },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, nvt_ts_i2c_id);
|
||||
|
||||
@@ -580,8 +580,8 @@ static const struct pixcir_i2c_chip_data pixcir_tangoc_data = {
|
||||
};
|
||||
|
||||
static const struct i2c_device_id pixcir_i2c_ts_id[] = {
|
||||
{ "pixcir_ts", (unsigned long) &pixcir_ts_data },
|
||||
{ "pixcir_tangoc", (unsigned long) &pixcir_tangoc_data },
|
||||
{ .name = "pixcir_ts", .driver_data = (unsigned long)&pixcir_ts_data },
|
||||
{ .name = "pixcir_tangoc", .driver_data = (unsigned long)&pixcir_tangoc_data },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id);
|
||||
|
||||
@@ -1219,8 +1219,8 @@ static DEFINE_SIMPLE_DEV_PM_OPS(raydium_i2c_pm_ops,
|
||||
raydium_i2c_suspend, raydium_i2c_resume);
|
||||
|
||||
static const struct i2c_device_id raydium_i2c_id[] = {
|
||||
{ "raydium_i2c" },
|
||||
{ "rm32380" },
|
||||
{ .name = "raydium_i2c" },
|
||||
{ .name = "rm32380" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, raydium_i2c_id);
|
||||
|
||||
@@ -1144,7 +1144,7 @@ static int rohm_bu21023_i2c_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id rohm_bu21023_i2c_id[] = {
|
||||
{ BU21023_NAME },
|
||||
{ .name = BU21023_NAME },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, rohm_bu21023_i2c_id);
|
||||
|
||||
@@ -520,7 +520,7 @@ MODULE_DEVICE_TABLE(of, s6sy761_of_match);
|
||||
#endif
|
||||
|
||||
static const struct i2c_device_id s6sy761_id[] = {
|
||||
{ "s6sy761" },
|
||||
{ .name = "s6sy761" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, s6sy761_id);
|
||||
|
||||
@@ -776,12 +776,12 @@ static int silead_ts_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(silead_ts_pm, silead_ts_suspend, silead_ts_resume);
|
||||
|
||||
static const struct i2c_device_id silead_ts_id[] = {
|
||||
{ "gsl1680" },
|
||||
{ "gsl1688" },
|
||||
{ "gsl3670" },
|
||||
{ "gsl3675" },
|
||||
{ "gsl3692" },
|
||||
{ "mssl1680" },
|
||||
{ .name = "gsl1680" },
|
||||
{ .name = "gsl1688" },
|
||||
{ .name = "gsl3670" },
|
||||
{ .name = "gsl3675" },
|
||||
{ .name = "gsl3692" },
|
||||
{ .name = "mssl1680" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, silead_ts_id);
|
||||
|
||||
@@ -374,8 +374,8 @@ MODULE_DEVICE_TABLE(of, sis_ts_dt_ids);
|
||||
#endif
|
||||
|
||||
static const struct i2c_device_id sis_ts_id[] = {
|
||||
{ SIS_I2C_NAME },
|
||||
{ "9200-ts" },
|
||||
{ .name = SIS_I2C_NAME },
|
||||
{ .name = "9200-ts" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, sis_ts_id);
|
||||
|
||||
@@ -453,8 +453,8 @@ static DEFINE_SIMPLE_DEV_PM_OPS(st1232_ts_pm_ops,
|
||||
st1232_ts_suspend, st1232_ts_resume);
|
||||
|
||||
static const struct i2c_device_id st1232_ts_id[] = {
|
||||
{ ST1232_TS_NAME, (unsigned long)&st1232_chip_info },
|
||||
{ ST1633_TS_NAME, (unsigned long)&st1633_chip_info },
|
||||
{ .name = ST1232_TS_NAME, .driver_data = (unsigned long)&st1232_chip_info },
|
||||
{ .name = ST1633_TS_NAME, .driver_data = (unsigned long)&st1633_chip_info },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, st1232_ts_id);
|
||||
|
||||
+990
-109
File diff suppressed because it is too large.
Load diff
@@ -43,7 +43,7 @@ static int tsc2004_probe(struct i2c_client *i2c)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id tsc2004_idtable[] = {
|
||||
{ "tsc2004" },
|
||||
{ .name = "tsc2004" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, tsc2004_idtable);
|
||||
|
||||
@@ -407,7 +407,7 @@ static int tsc2007_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id tsc2007_idtable[] = {
|
||||
{ "tsc2007" },
|
||||
{ .name = "tsc2007" },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
@@ -253,7 +253,7 @@ static int wacom_i2c_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(wacom_i2c_pm, wacom_i2c_suspend, wacom_i2c_resume);
|
||||
|
||||
static const struct i2c_device_id wacom_i2c_id[] = {
|
||||
{ "WAC_I2C_EMR" },
|
||||
{ .name = "WAC_I2C_EMR" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, wacom_i2c_id);
|
||||
|
||||
@@ -1140,7 +1140,7 @@ static int wdt87xx_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(wdt87xx_pm_ops, wdt87xx_suspend, wdt87xx_resume);
|
||||
|
||||
static const struct i2c_device_id wdt87xx_dev_id[] = {
|
||||
{ WDT87XX_NAME },
|
||||
{ .name = WDT87XX_NAME },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, wdt87xx_dev_id);
|
||||
|
||||
@@ -236,7 +236,7 @@ static const struct of_device_id zet6223_of_match[] = {
|
||||
MODULE_DEVICE_TABLE(of, zet6223_of_match);
|
||||
|
||||
static const struct i2c_device_id zet6223_id[] = {
|
||||
{ "zet6223" },
|
||||
{ .name = "zet6223" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, zet6223_id);
|
||||
|
||||
@@ -831,7 +831,7 @@ static int zforce_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id zforce_idtable[] = {
|
||||
{ "zforce-ts" },
|
||||
{ .name = "zforce-ts" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, zforce_idtable);
|
||||
|
||||
@@ -53,6 +53,10 @@ static const struct resource thermal_resources[] = {
|
||||
DEFINE_RES_IRQ(MAX77620_IRQ_LBT_TJALRM2),
|
||||
};
|
||||
|
||||
static const struct resource onoff_resources[] = {
|
||||
DEFINE_RES_IRQ(MAX77620_IRQ_TOP_ONOFF),
|
||||
};
|
||||
|
||||
static const struct regmap_irq max77620_top_irqs[] = {
|
||||
REGMAP_IRQ_REG(MAX77620_IRQ_TOP_GLBL, 0, MAX77620_IRQ_TOP_GLBL_MASK),
|
||||
REGMAP_IRQ_REG(MAX77620_IRQ_TOP_SD, 0, MAX77620_IRQ_TOP_SD_MASK),
|
||||
@@ -87,6 +91,10 @@ static const struct mfd_cell max77620_children[] = {
|
||||
.name = "max77620-thermal",
|
||||
.resources = thermal_resources,
|
||||
.num_resources = ARRAY_SIZE(thermal_resources),
|
||||
}, {
|
||||
.name = "max77620-onoff",
|
||||
.resources = onoff_resources,
|
||||
.num_resources = ARRAY_SIZE(onoff_resources),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -195,3 +195,13 @@ config SOC_TEGRA_CBB
|
||||
Support for handling error from Tegra Control Backbone(CBB).
|
||||
This driver handles the errors from CBB and prints debug
|
||||
information about the failed transactions.
|
||||
|
||||
config SOC_TEGRA_R2P
|
||||
tristate "Tegra Reboot 2 Payload support"
|
||||
depends on ARCH_TEGRA_124_SOC || ARCH_TEGRA_210_SOC
|
||||
default n
|
||||
help
|
||||
This enables a special reboot path which allows the board to reboot
|
||||
to a specified bootloader other than the one in boot storage.
|
||||
|
||||
If in doubt, say N.
|
||||
@@ -8,3 +8,4 @@ obj-$(CONFIG_SOC_TEGRA_PMC) += pmc.o
|
||||
obj-$(CONFIG_SOC_TEGRA20_VOLTAGE_COUPLER) += regulators-tegra20.o
|
||||
obj-$(CONFIG_SOC_TEGRA30_VOLTAGE_COUPLER) += regulators-tegra30.o
|
||||
obj-$(CONFIG_ARCH_TEGRA_186_SOC) += ari-tegra186.o
|
||||
obj-$(CONFIG_SOC_TEGRA_R2P) += r2p-tegra.o
|
||||
+405
-15
@@ -35,6 +35,7 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/panic_notifier.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
@@ -111,6 +112,8 @@
|
||||
|
||||
#define PMC_PWR_DET_VALUE 0xe4
|
||||
|
||||
#define KERNEL_PANIC_MAGIC 0x4E415054
|
||||
|
||||
#define PMC_USB_DEBOUNCE_DEL 0xec
|
||||
#define PMC_USB_AO 0xf0
|
||||
|
||||
@@ -177,6 +180,26 @@
|
||||
#define PMC_UTMIP_PAD_CFG0 0x4c0
|
||||
#define PMC_UTMIP_UHSIC_SLEEP_CFG1 0x4d0
|
||||
#define PMC_UTMIP_SLEEPWALK_P3 0x4e0
|
||||
|
||||
/* Scratch 250: Bootrom i2c command base */
|
||||
#define PMC_BR_COMMAND_BASE 0x908
|
||||
|
||||
/* Bootrom comand register */
|
||||
#define PMC_REG_8bit_MASK 0xFF
|
||||
#define PMC_REG_16bit_MASK 0xFFFF
|
||||
#define PMC_BR_COMMAND_I2C_ADD_MASK 0x7F
|
||||
#define PMC_BR_COMMAND_WR_COMMANDS_MASK 0x3F
|
||||
#define PMC_BR_COMMAND_WR_COMMANDS_SHIFT 8
|
||||
#define PMC_BR_COMMAND_OPERAND_SHIFT 15
|
||||
#define PMC_BR_COMMAND_CSUM_MASK 0xFF
|
||||
#define PMC_BR_COMMAND_CSUM_SHIFT 16
|
||||
#define PMC_BR_COMMAND_PMUX_MASK 0x7
|
||||
#define PMC_BR_COMMAND_PMUX_SHIFT 24
|
||||
#define PMC_BR_COMMAND_CTRL_ID_MASK 0x7
|
||||
#define PMC_BR_COMMAND_CTRL_ID_SHIFT 27
|
||||
#define PMC_BR_COMMAND_CTRL_TYPE_SHIFT 30
|
||||
#define PMC_BR_COMMAND_RST_EN_SHIFT 31
|
||||
|
||||
/* Tegra186 and later */
|
||||
#define WAKE_AOWAKE_CNTRL(x) (0x000 + ((x) << 2))
|
||||
#define WAKE_AOWAKE_CNTRL_LEVEL (1 << 3)
|
||||
@@ -292,6 +315,29 @@ struct tegra_powergate {
|
||||
struct reset_control *reset;
|
||||
};
|
||||
|
||||
struct tegra_bootrom_block {
|
||||
const char *name;
|
||||
int address;
|
||||
bool reg_8bits;
|
||||
bool data_8bits;
|
||||
bool i2c_controller;
|
||||
int controller_id;
|
||||
bool enable_reset;
|
||||
int ncommands;
|
||||
u32 *commands;
|
||||
};
|
||||
|
||||
struct tegra_bootrom_commands {
|
||||
u32 command_retry_count;
|
||||
u32 delay_between_commands;
|
||||
u32 wait_before_bus_clear;
|
||||
struct tegra_bootrom_block *blocks;
|
||||
int nblocks;
|
||||
};
|
||||
|
||||
static struct tegra_bootrom_commands *br_rst_commands;
|
||||
static struct tegra_bootrom_commands *br_off_commands;
|
||||
|
||||
struct tegra_io_pad_soc {
|
||||
enum tegra_io_pad id;
|
||||
unsigned int dpd;
|
||||
@@ -378,6 +424,7 @@ struct tegra_pmc_soc {
|
||||
bool needs_mbist_war;
|
||||
bool has_io_pad_wren;
|
||||
bool maybe_tz_only;
|
||||
bool has_bootrom_command;
|
||||
|
||||
const struct tegra_io_pad_soc *io_pads;
|
||||
unsigned int num_io_pads;
|
||||
@@ -419,6 +466,8 @@ struct tegra_pmc_soc {
|
||||
bool has_usb_sleepwalk;
|
||||
bool supports_core_domain;
|
||||
bool has_single_mmio_aperture;
|
||||
|
||||
bool cboot_panic_notifier;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -505,6 +554,7 @@ struct tegra_pmc {
|
||||
unsigned long *wake_cntrl_level_map;
|
||||
|
||||
struct notifier_block reboot_notifier;
|
||||
struct notifier_block panic_notifier;
|
||||
struct syscore syscore;
|
||||
|
||||
/* Pending wake IRQ processing */
|
||||
@@ -523,7 +573,8 @@ to_powergate(struct generic_pm_domain *domain)
|
||||
return container_of(domain, struct tegra_powergate, genpd);
|
||||
}
|
||||
|
||||
static u32 tegra_pmc_readl(struct tegra_pmc *pmc, unsigned long offset)
|
||||
// FIXME this prolly should not be public
|
||||
u32 tegra_pmc_readl(struct tegra_pmc *pmc, unsigned long offset)
|
||||
{
|
||||
struct arm_smccc_res res;
|
||||
|
||||
@@ -544,6 +595,7 @@ static u32 tegra_pmc_readl(struct tegra_pmc *pmc, unsigned long offset)
|
||||
|
||||
return readl(pmc->base + offset);
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_pmc_readl);
|
||||
|
||||
static void tegra_pmc_writel(struct tegra_pmc *pmc, u32 value,
|
||||
unsigned long offset)
|
||||
@@ -1310,21 +1362,10 @@ static int tegra_pmc_restart_handler(struct sys_off_data *data)
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static int tegra_pmc_power_off_handler(struct sys_off_data *data)
|
||||
static int tegra_pmc_panic_handler(struct notifier_block *this,
|
||||
unsigned long action, void *data)
|
||||
{
|
||||
struct tegra_pmc *pmc = data->cb_data;
|
||||
|
||||
/*
|
||||
* Reboot Nexus 7 into special bootloader mode if USB cable is
|
||||
* connected in order to display battery status and power off.
|
||||
*/
|
||||
if (of_machine_is_compatible("asus,grouper") &&
|
||||
power_supply_is_system_supplied()) {
|
||||
const u32 go_to_charger_mode = 0xa5a55a5a;
|
||||
|
||||
tegra_pmc_writel(pmc, go_to_charger_mode, PMC_SCRATCH37);
|
||||
tegra_pmc_restart(pmc);
|
||||
}
|
||||
tegra_pmc_writel(pmc, KERNEL_PANIC_MAGIC, PMC_SCRATCH37);
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
@@ -1698,6 +1739,330 @@ static void tegra_powergate_remove_all(struct device_node *parent)
|
||||
}
|
||||
}
|
||||
|
||||
static int tegra_pmc_parse_bootrom_cmd(struct device *dev,
|
||||
struct device_node *np,
|
||||
struct tegra_bootrom_commands **br_cmds)
|
||||
{
|
||||
struct device_node *child;
|
||||
struct tegra_bootrom_commands *bcommands;
|
||||
int *command_ptr;
|
||||
struct tegra_bootrom_block *block;
|
||||
int nblocks;
|
||||
u32 reg, data, pval;
|
||||
u32 *wr_commands;
|
||||
int count, nblock, ncommands, i, data_shift;
|
||||
int ret;
|
||||
int sz_bcommand, sz_blocks;
|
||||
|
||||
nblocks = of_get_available_child_count(np);
|
||||
if (!nblocks) {
|
||||
dev_info(dev, "PMC: No Bootrom Command\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
count = 0;
|
||||
for_each_available_child_of_node(np, child) {
|
||||
ret = of_property_count_u32_elems(child,
|
||||
"nvidia,write-commands");
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "PMC: Node %s does not have write-commnds\n",
|
||||
child->full_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
count += ret / 2;
|
||||
}
|
||||
|
||||
sz_bcommand = (sizeof(*bcommands) + 0x3) & ~0x3;
|
||||
sz_blocks = (sizeof(*block) + 0x3) & ~0x3;
|
||||
bcommands = devm_kzalloc(dev, sz_bcommand + nblocks * sz_blocks +
|
||||
count * sizeof(u32), GFP_KERNEL);
|
||||
if (!bcommands)
|
||||
return -ENOMEM;
|
||||
|
||||
bcommands->nblocks = nblocks;
|
||||
bcommands->blocks = (void *)bcommands + sz_bcommand;
|
||||
command_ptr = (void *)bcommands->blocks + nblocks * sz_blocks;
|
||||
|
||||
of_property_read_u32(np, "nvidia,command-retries-count",
|
||||
&bcommands->command_retry_count);
|
||||
of_property_read_u32(np, "nvidia,delay-between-commands-us",
|
||||
&bcommands->delay_between_commands);
|
||||
|
||||
ret = of_property_read_u32(np, "nvidia,wait-before-start-bus-clear-us",
|
||||
&bcommands->wait_before_bus_clear);
|
||||
if (ret < 0)
|
||||
of_property_read_u32(np, "nvidia,wait-start-bus-clear-us",
|
||||
&bcommands->wait_before_bus_clear);
|
||||
|
||||
nblock = 0;
|
||||
for_each_available_child_of_node(np, child) {
|
||||
block = &bcommands->blocks[nblock];
|
||||
ret = of_property_read_u32(child, "reg", &pval);
|
||||
if (ret) {
|
||||
dev_err(dev, "PMC: Reg property missing on block %s\n",
|
||||
child->name);
|
||||
return ret;
|
||||
}
|
||||
block->address = pval;
|
||||
of_property_read_string(child, "nvidia,command-names",
|
||||
&block->name);
|
||||
block->reg_8bits = !of_property_read_bool(child,
|
||||
"nvidia,enable-16bit-register");
|
||||
block->data_8bits = !of_property_read_bool(child,
|
||||
"nvidia,enable-16bit-data");
|
||||
block->i2c_controller = of_property_read_bool(child,
|
||||
"nvidia,controller-type-i2c");
|
||||
block->enable_reset = of_property_read_bool(child,
|
||||
"nvidia,enable-controller-reset");
|
||||
count = of_property_count_u32_elems(child,
|
||||
"nvidia,write-commands");
|
||||
ncommands = count / 2;
|
||||
|
||||
block->commands = command_ptr;
|
||||
command_ptr += ncommands;
|
||||
wr_commands = block->commands;
|
||||
data_shift = (block->data_8bits) ? 8 : 16;
|
||||
for (i = 0; i < ncommands; ++i) {
|
||||
of_property_read_u32_index(child,
|
||||
"nvidia,write-commands",
|
||||
i * 2, ®);
|
||||
of_property_read_u32_index(child,
|
||||
"nvidia,write-commands",
|
||||
i * 2 + 1, &data);
|
||||
|
||||
wr_commands[i] = (data << data_shift) | reg;
|
||||
}
|
||||
block->ncommands = ncommands;
|
||||
nblock++;
|
||||
}
|
||||
*br_cmds = bcommands;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_pmc_read_bootrom_cmd(struct device *dev,
|
||||
struct tegra_bootrom_commands **br_rst_cmds,
|
||||
struct tegra_bootrom_commands **br_off_cmds)
|
||||
{
|
||||
struct device_node *np = dev->of_node;
|
||||
struct device_node *br_np, *rst_np, *off_np;
|
||||
int ret;
|
||||
|
||||
*br_rst_cmds = NULL;
|
||||
*br_off_cmds = NULL;
|
||||
|
||||
br_np = of_find_node_by_name(np, "bootrom-commands");
|
||||
if (!br_np) {
|
||||
dev_info(dev, "PMC: Bootrom commmands not found\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
rst_np = of_find_node_by_name(br_np, "reset-commands");
|
||||
if (!rst_np) {
|
||||
dev_info(dev, "PMC: bootrom-commands used for reset\n");
|
||||
rst_np = br_np;
|
||||
}
|
||||
|
||||
ret = tegra_pmc_parse_bootrom_cmd(dev, rst_np, br_rst_cmds);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (rst_np == br_np)
|
||||
return 0;
|
||||
|
||||
off_np = of_find_node_by_name(br_np, "power-off-commands");
|
||||
if (!off_np)
|
||||
return 0;
|
||||
ret = tegra_pmc_parse_bootrom_cmd(dev, off_np, br_off_cmds);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_pmc_configure_bootrom_scratch(struct tegra_pmc *pmc,
|
||||
struct tegra_bootrom_commands *br_commands,
|
||||
struct tegra_br_cmd_cfg *bcfg, u32 bcfg_size)
|
||||
{
|
||||
struct tegra_bootrom_block *block;
|
||||
int i, j, k;
|
||||
u32 cmd, tmp_cmd;
|
||||
int reg_offset = 1;
|
||||
int bcfg_idx = 0;
|
||||
u32 reg_data_mask, edit_data_mask;
|
||||
int cmd_pw;
|
||||
u32 block_add, block_val, csum;
|
||||
|
||||
for (i = 0; i < br_commands->nblocks; ++i) {
|
||||
block = &br_commands->blocks[i];
|
||||
|
||||
cmd = block->address & PMC_BR_COMMAND_I2C_ADD_MASK;
|
||||
cmd |= block->ncommands << PMC_BR_COMMAND_WR_COMMANDS_SHIFT;
|
||||
if (!block->reg_8bits || !block->data_8bits)
|
||||
cmd |= BIT(PMC_BR_COMMAND_OPERAND_SHIFT);
|
||||
|
||||
if (block->enable_reset)
|
||||
cmd |= BIT(PMC_BR_COMMAND_RST_EN_SHIFT);
|
||||
|
||||
cmd |= (block->controller_id & PMC_BR_COMMAND_CTRL_ID_MASK) <<
|
||||
PMC_BR_COMMAND_CTRL_ID_SHIFT;
|
||||
|
||||
/* Checksum will be added after parsing from reg/data */
|
||||
tegra_pmc_writel(pmc, cmd, PMC_BR_COMMAND_BASE + (reg_offset * 4));
|
||||
block_add = reg_offset * 4;
|
||||
block_val = cmd;
|
||||
reg_offset++;
|
||||
|
||||
cmd_pw = (block->reg_8bits && block->data_8bits) ? 2 : 1;
|
||||
reg_data_mask = (cmd_pw == 2) ? 0xFFFF : 0xFFFFFFFFUL;
|
||||
csum = 0;
|
||||
|
||||
for (j = 0; j < block->ncommands; j++) {
|
||||
tmp_cmd = block->commands[j] & reg_data_mask;
|
||||
if (bcfg_idx < bcfg_size &&
|
||||
bcfg[bcfg_idx].dev == i &&
|
||||
bcfg[bcfg_idx].idx == j) {
|
||||
edit_data_mask = (cmd_pw == 2) ?
|
||||
0xFF00UL : 0xFFFF0000UL;
|
||||
tmp_cmd &= ~edit_data_mask;
|
||||
tmp_cmd |= (bcfg[bcfg_idx].val <<
|
||||
(cmd_pw == 2 ? 8 : 16)) & edit_data_mask;
|
||||
bcfg_idx++;
|
||||
}
|
||||
cmd = tmp_cmd;
|
||||
if (cmd_pw == 2) {
|
||||
j++;
|
||||
if (j == block->ncommands)
|
||||
goto reg_update;
|
||||
|
||||
tmp_cmd = (block->commands[j] & reg_data_mask) << 16;
|
||||
if (bcfg_idx < bcfg_size &&
|
||||
bcfg[bcfg_idx].dev == i &&
|
||||
bcfg[bcfg_idx].idx == j) {
|
||||
edit_data_mask = 0xFF000000UL;
|
||||
tmp_cmd &= ~edit_data_mask;
|
||||
tmp_cmd |= (bcfg[bcfg_idx].val << 24) &
|
||||
edit_data_mask;
|
||||
bcfg_idx++;
|
||||
}
|
||||
cmd |= tmp_cmd;
|
||||
}
|
||||
reg_update:
|
||||
tegra_pmc_writel(pmc, cmd, PMC_BR_COMMAND_BASE + (reg_offset * 4));
|
||||
for (k = 0; k < 4; ++k)
|
||||
csum += (cmd >> (k * 8)) & 0xFF;
|
||||
reg_offset++;
|
||||
}
|
||||
for (k = 0; k < 4; ++k)
|
||||
csum += (block_val >> (k * 8)) & 0xFF;
|
||||
csum = 0x100 - csum;
|
||||
block_val = (block_val & 0xFF00FFFF) | ((csum & 0xFF) << 16);
|
||||
tegra_pmc_writel(pmc, block_val, PMC_BR_COMMAND_BASE + block_add);
|
||||
}
|
||||
|
||||
cmd = br_commands->command_retry_count & 0x7;
|
||||
cmd |= (br_commands->delay_between_commands & 0x1F) << 3;
|
||||
cmd |= (br_commands->nblocks & 0x7) << 8;
|
||||
cmd |= (br_commands->wait_before_bus_clear & 0x1F) << 11;
|
||||
tegra_pmc_writel(pmc, cmd, PMC_BR_COMMAND_BASE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* tegra_pmc_edit_bootrom_scratch_reset() - configure brom reset commands
|
||||
* @pmc: power management controller
|
||||
* @bcfg: bootrom command config structure
|
||||
* @bcfg_size: size of bcfg
|
||||
*
|
||||
* Returns: 0 on success or a negative error code on failure.
|
||||
*/
|
||||
int tegra_pmc_edit_bootrom_scratch_reset(struct tegra_pmc *pmc,
|
||||
struct tegra_br_cmd_cfg *bcfg, u32 bcfg_size)
|
||||
{
|
||||
if (br_rst_commands) {
|
||||
tegra_pmc_configure_bootrom_scratch(pmc, br_rst_commands,
|
||||
bcfg, bcfg_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_pmc_edit_bootrom_scratch_reset);
|
||||
|
||||
static int tegra_pmc_init_bootrom_power_off_cmd(struct tegra_pmc *pmc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!br_off_commands) {
|
||||
dev_info(pmc->dev, "PMC: Power Off Command not available\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = tegra_pmc_configure_bootrom_scratch(pmc, br_off_commands, NULL, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(pmc->dev, "PMC: Failed to configure power-off command: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_info(pmc->dev, "PMC: Successfully configure power-off commands\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_pmc_init_bootrom_cmds(struct tegra_pmc *pmc, struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = tegra_pmc_read_bootrom_cmd(dev, &br_rst_commands,
|
||||
&br_off_commands);
|
||||
if (ret < 0) {
|
||||
if (ret == -ENOENT)
|
||||
ret = 0;
|
||||
else
|
||||
dev_info(dev,
|
||||
"PMC: Failed to read bootrom cmd: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = tegra_pmc_configure_bootrom_scratch(pmc, br_rst_commands, NULL, 0);
|
||||
if (ret < 0) {
|
||||
dev_info(dev, "PMC: Failed to write bootrom scratch register: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_info(dev, "PMC: Successfully configure bootrom reset commands\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_pmc_power_off_handler(struct sys_off_data *data)
|
||||
{
|
||||
struct tegra_pmc *pmc = data->cb_data;
|
||||
|
||||
if (br_off_commands) {
|
||||
tegra_pmc_init_bootrom_power_off_cmd(pmc);
|
||||
tegra_pmc_restart(pmc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reboot Nexus 7 into special bootloader mode if USB cable is
|
||||
* connected in order to display battery status and power off.
|
||||
*/
|
||||
if (of_machine_is_compatible("asus,grouper") &&
|
||||
power_supply_is_system_supplied()) {
|
||||
const u32 go_to_charger_mode = 0xa5a55a5a;
|
||||
|
||||
tegra_pmc_writel(pmc, go_to_charger_mode, PMC_SCRATCH37);
|
||||
tegra_pmc_restart(pmc);
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static const struct tegra_io_pad_soc *
|
||||
tegra_io_pad_find(struct tegra_pmc *pmc, enum tegra_io_pad id)
|
||||
{
|
||||
@@ -3182,6 +3547,9 @@ static int tegra_pmc_probe(struct platform_device *pdev)
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(pmc->clk),
|
||||
"failed to get pclk\n");
|
||||
|
||||
if (pmc->soc->has_bootrom_command)
|
||||
tegra_pmc_init_bootrom_cmds(pmc, &pdev->dev);
|
||||
|
||||
/*
|
||||
* PMC should be last resort for restarting since it soft-resets
|
||||
* CPU without resetting everything else.
|
||||
@@ -3199,6 +3567,20 @@ static int tegra_pmc_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
if (pmc->soc->cboot_panic_notifier) {
|
||||
pmc->panic_notifier.notifier_call = tegra_pmc_panic_handler;
|
||||
pmc->panic_notifier.priority = INT_MAX-1;
|
||||
|
||||
err = atomic_notifier_chain_register(&panic_notifier_list,
|
||||
&pmc->panic_notifier);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev,
|
||||
"unable to register panic notifier, %d\n",
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
err = devm_register_sys_off_handler(&pdev->dev,
|
||||
SYS_OFF_MODE_RESTART,
|
||||
SYS_OFF_PRIO_LOW,
|
||||
@@ -3566,6 +3948,7 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = {
|
||||
.has_blink_output = true,
|
||||
.has_usb_sleepwalk = true,
|
||||
.has_single_mmio_aperture = true,
|
||||
.has_bootrom_command = false,
|
||||
};
|
||||
|
||||
static const char * const tegra30_powergates[] = {
|
||||
@@ -3628,6 +4011,7 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = {
|
||||
.has_blink_output = true,
|
||||
.has_usb_sleepwalk = true,
|
||||
.has_single_mmio_aperture = true,
|
||||
.has_bootrom_command = false,
|
||||
};
|
||||
|
||||
static const char * const tegra114_powergates[] = {
|
||||
@@ -3686,6 +4070,7 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = {
|
||||
.has_blink_output = true,
|
||||
.has_usb_sleepwalk = true,
|
||||
.has_single_mmio_aperture = true,
|
||||
.has_bootrom_command = false,
|
||||
};
|
||||
|
||||
static const char * const tegra124_powergates[] = {
|
||||
@@ -3838,6 +4223,7 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = {
|
||||
.has_blink_output = true,
|
||||
.has_usb_sleepwalk = true,
|
||||
.has_single_mmio_aperture = true,
|
||||
.has_bootrom_command = false,
|
||||
};
|
||||
|
||||
static const char * const tegra210_powergates[] = {
|
||||
@@ -4018,6 +4404,8 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = {
|
||||
.has_blink_output = true,
|
||||
.has_usb_sleepwalk = true,
|
||||
.has_single_mmio_aperture = true,
|
||||
.cboot_panic_notifier = true,
|
||||
.has_bootrom_command = true,
|
||||
};
|
||||
|
||||
static const char * const tegra210b01_powergates[] = {
|
||||
@@ -4079,6 +4467,8 @@ static const struct tegra_pmc_soc tegra210b01_pmc_soc = {
|
||||
.has_blink_output = true,
|
||||
.has_usb_sleepwalk = true,
|
||||
.has_single_mmio_aperture = true,
|
||||
.cboot_panic_notifier = true,
|
||||
.has_bootrom_command = true,
|
||||
};
|
||||
|
||||
static const struct tegra_io_pad_soc tegra186_io_pads[] = {
|
||||
|
||||
@@ -0,0 +1,485 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Ezekiel Bethel <zek@9net.org>
|
||||
* Copyright (c) 2021-2022, CTCaer <ctcaer@gmail.com>
|
||||
* Copyright (c) 2026 Thomas Makin <halorocker89@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <soc/tegra/pmc.h>
|
||||
|
||||
#define TEGRA_SIP_R2P_COPY_TO_IRAM 0xC2FFFE02u
|
||||
#define R2P_WRITE_IRAM (0U << 0)
|
||||
#define R2P_READ_IRAM (1U << 0)
|
||||
#define TEGRA_SIP_R2P_DO_REBOOT 0xC2FFFE03u
|
||||
#define TEGRA_SIP_R2P_SET_BIN_CFG 0xC2FFFE04u
|
||||
|
||||
#define IRAM_PAYLOAD_BASE 0x40010000u
|
||||
#define IRAM_CHUNK_SIZE 0x4000
|
||||
|
||||
#define KERNEL_PANIC_MAGIC 0x4E415054
|
||||
#define RTC_REBOOT_REASON_MAGIC 0x77
|
||||
#define PMC_SCRATCH37 0x130
|
||||
|
||||
/* hekate/Nyx */
|
||||
#define BOOT_CFG_AUTOBOOT_EN BIT(0)
|
||||
#define BOOT_CFG_FROM_ID BIT(2)
|
||||
|
||||
#define EXTRA_CFG_NYX_UMS BIT(5)
|
||||
#define EXTRA_CFG_NYX_RELOAD BIT(6)
|
||||
|
||||
enum {
|
||||
NYX_UMS_SD_CARD = 0,
|
||||
NYX_UMS_EMMC_BOOT0,
|
||||
NYX_UMS_EMMC_BOOT1,
|
||||
NYX_UMS_EMMC_GPP,
|
||||
NYX_UMS_EMUMMC_BOOT0,
|
||||
NYX_UMS_EMUMMC_BOOT1,
|
||||
NYX_UMS_EMUMMC_GPP
|
||||
};
|
||||
|
||||
enum {
|
||||
REBOOT_REASON_NOP = 0, /* Use [config]. */
|
||||
REBOOT_REASON_SELF = 1, /* Use autoboot_idx/autoboot_list. */
|
||||
REBOOT_REASON_MENU = 2, /* Force menu. */
|
||||
REBOOT_REASON_UMS = 3, /* Force selected UMS partition. */
|
||||
REBOOT_REASON_REC = 4, /* Set PMC_SCRATCH0_MODE_RECOVERY and reboot to self. */
|
||||
REBOOT_REASON_PANIC = 5 /* Inform bootloader that panic occured if T210B01. */
|
||||
};
|
||||
|
||||
struct __attribute__((__packed__)) hekate_boot_cfg
|
||||
{
|
||||
u8 boot_cfg;
|
||||
u8 autoboot;
|
||||
u8 autoboot_list;
|
||||
u8 extra_cfg;
|
||||
union {
|
||||
struct {
|
||||
char id[8];
|
||||
char emummc_path[0x78];
|
||||
};
|
||||
u8 ums;
|
||||
u8 xt_str[0x80];
|
||||
};
|
||||
};
|
||||
|
||||
struct rtc_rr_dec
|
||||
{
|
||||
u16 reason:4;
|
||||
u16 autoboot_idx:4;
|
||||
u16 autoboot_list:1;
|
||||
u16 ums_idx:3;
|
||||
};
|
||||
|
||||
struct rtc_rr_enc
|
||||
{
|
||||
u16 val1:6; /* 6-bit reg. */
|
||||
u16 val2:6; /* 6-bit reg. */
|
||||
};
|
||||
|
||||
struct rtc_reboot_reason
|
||||
{
|
||||
union {
|
||||
struct rtc_rr_dec dec;
|
||||
struct rtc_rr_enc enc;
|
||||
};
|
||||
};
|
||||
|
||||
struct tegra_r2p_data
|
||||
{
|
||||
struct device *dev;
|
||||
struct tegra_pmc *pmc;
|
||||
struct notifier_block reboot_notifier;
|
||||
|
||||
char action[16];
|
||||
int param1;
|
||||
int param2;
|
||||
char entry_id[8];
|
||||
};
|
||||
|
||||
static int enabled = 0;
|
||||
static int param1 = 0;
|
||||
static int param2 = 0;
|
||||
static char* action = NULL;
|
||||
static char* entry_id = NULL;
|
||||
|
||||
module_param(enabled, int, 0664);
|
||||
module_param(action, charp, 0664);
|
||||
module_param(param1, int, 0664);
|
||||
module_param(param2, int, 0664);
|
||||
module_param(entry_id, charp, 0664);
|
||||
|
||||
MODULE_PARM_DESC(enabled, "Enable Reboot 2 Payload function");
|
||||
MODULE_PARM_DESC(action, "Reboot action to take");
|
||||
MODULE_PARM_DESC(param1, "Autoboot entry or UMS device index");
|
||||
MODULE_PARM_DESC(param2, "Autooboot entry is ini list");
|
||||
MODULE_PARM_DESC(entry_id, "Autoboot entry id");
|
||||
|
||||
struct platform_device *r2p_device = NULL;
|
||||
|
||||
static u32 tegra_r2p_set_cfg(struct hekate_boot_cfg *hekate_bcfg)
|
||||
{
|
||||
struct arm_smccc_res res;
|
||||
u64 hekate_boot_smc_cfg[4];
|
||||
|
||||
memcpy(hekate_boot_smc_cfg, hekate_bcfg, sizeof(hekate_boot_smc_cfg));
|
||||
arm_smccc_smc(TEGRA_SIP_R2P_SET_BIN_CFG, hekate_boot_smc_cfg[0], hekate_boot_smc_cfg[1],
|
||||
hekate_boot_smc_cfg[2], hekate_boot_smc_cfg[3], 0, 0, 0, &res);
|
||||
return (u32)res.a1;
|
||||
}
|
||||
|
||||
static void tegra_r2p_setup(struct tegra_r2p_data *state, const char *cmd)
|
||||
{
|
||||
struct rtc_reboot_reason rr = {};
|
||||
struct hekate_boot_cfg hekate_bcfg = {};
|
||||
struct tegra_pmc *pmc = state->pmc;
|
||||
|
||||
uint32_t reboot_reason = REBOOT_REASON_NOP;
|
||||
bool tegra210b01 = of_device_is_compatible(state->dev->of_node, "nvidia,tegra210b01-r2p");
|
||||
|
||||
u32 panic_code = tegra_pmc_readl(pmc, PMC_SCRATCH37);
|
||||
bool panic_occurred = (panic_code == KERNEL_PANIC_MAGIC);
|
||||
|
||||
if (r2p_device == NULL) {
|
||||
dev_err(&r2p_device->dev, "r2p device is null\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Linux reboot reason */
|
||||
if (cmd) {
|
||||
if (!strcmp(cmd, "recovery")) {
|
||||
reboot_reason = REBOOT_REASON_REC;
|
||||
} else if (!strcmp(cmd, "bootloader")) {
|
||||
reboot_reason = REBOOT_REASON_MENU;
|
||||
} else if (!strcmp(cmd, "forced-recovery")) { /* RCM */
|
||||
if (tegra210b01) return;
|
||||
} else {
|
||||
dev_err(&r2p_device->dev,
|
||||
"Command '%s' not recognized\n", cmd);
|
||||
}
|
||||
}
|
||||
|
||||
/* Missing reboot reason or not matching, use r2p action. */
|
||||
if (reboot_reason == REBOOT_REASON_NOP && strlen(state->action)) {
|
||||
if (!strcmp(state->action, "self") ||
|
||||
!strcmp(state->action, "via-payload")) { /* Deprecated */
|
||||
reboot_reason = REBOOT_REASON_SELF;
|
||||
} else if (!strcmp(state->action, "bootloader")) {
|
||||
reboot_reason = REBOOT_REASON_MENU;
|
||||
} else if (!strcmp(state->action, "ums")) {
|
||||
reboot_reason = REBOOT_REASON_UMS;
|
||||
} else if (!strcmp(state->action, "normal")) {
|
||||
reboot_reason = REBOOT_REASON_NOP;
|
||||
} else {
|
||||
dev_err(&r2p_device->dev,
|
||||
"Action '%s' not recognized\n", state->action);
|
||||
}
|
||||
}
|
||||
|
||||
/* If T210B01 and panic happened override reboot reason */
|
||||
if (tegra210b01 && panic_occurred) {
|
||||
reboot_reason = REBOOT_REASON_PANIC;
|
||||
}
|
||||
|
||||
/* Prepare boot config data */
|
||||
switch (reboot_reason) {
|
||||
case REBOOT_REASON_NOP:
|
||||
if (tegra210b01) return;
|
||||
break;
|
||||
case REBOOT_REASON_REC:
|
||||
case REBOOT_REASON_SELF:
|
||||
hekate_bcfg.boot_cfg = BOOT_CFG_AUTOBOOT_EN;
|
||||
if (strlen(state->entry_id) != 0) {
|
||||
hekate_bcfg.boot_cfg |= BOOT_CFG_FROM_ID;
|
||||
strcpy(hekate_bcfg.id, state->entry_id);
|
||||
}
|
||||
hekate_bcfg.autoboot = state->param1;
|
||||
hekate_bcfg.autoboot_list = state->param2;
|
||||
|
||||
rr.dec.reason = reboot_reason;
|
||||
rr.dec.autoboot_idx = state->param1;
|
||||
rr.dec.autoboot_list = state->param2;
|
||||
break;
|
||||
case REBOOT_REASON_MENU:
|
||||
hekate_bcfg.boot_cfg = BOOT_CFG_AUTOBOOT_EN;
|
||||
|
||||
rr.dec.reason = reboot_reason;
|
||||
break;
|
||||
case REBOOT_REASON_UMS:
|
||||
hekate_bcfg.boot_cfg = BOOT_CFG_AUTOBOOT_EN;
|
||||
hekate_bcfg.extra_cfg = EXTRA_CFG_NYX_UMS;
|
||||
hekate_bcfg.ums = state->param1;
|
||||
|
||||
rr.dec.reason = reboot_reason;
|
||||
rr.dec.ums_idx = state->param1;
|
||||
break;
|
||||
case REBOOT_REASON_PANIC:
|
||||
rr.dec.reason = reboot_reason;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Notify TZ to use its preloaded payload */
|
||||
if (!tegra210b01) {
|
||||
/* Set hekate boot config. */
|
||||
tegra_r2p_set_cfg(&hekate_bcfg);
|
||||
} else {
|
||||
struct tegra_br_cmd_cfg bcfg[4] = {
|
||||
{ 0, 0, rr.enc.val1 },
|
||||
{ 0, 1, rr.enc.val2 },
|
||||
{ 0, 2, RTC_REBOOT_REASON_MAGIC },
|
||||
{ 0, 3, RTC_REBOOT_REASON_MAGIC }
|
||||
};
|
||||
tegra_pmc_edit_bootrom_scratch_reset(pmc, bcfg, 4);
|
||||
}
|
||||
}
|
||||
|
||||
static int tegra_r2p_reboot_notify(struct notifier_block *this,
|
||||
unsigned long action, void *data)
|
||||
{
|
||||
struct tegra_r2p_data *state = container_of(this, struct tegra_r2p_data,
|
||||
reboot_notifier);
|
||||
if (action == SYS_RESTART)
|
||||
tegra_r2p_setup(state, data);
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static ssize_t action_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct tegra_r2p_data *state = dev_get_drvdata(&r2p_device->dev);
|
||||
int res;
|
||||
|
||||
if (strlen(state->action))
|
||||
res = sprintf(buf, "%s\n", state->action);
|
||||
else
|
||||
res = sprintf(buf, "Not-set\n");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t action_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
struct tegra_r2p_data *state = dev_get_drvdata(&r2p_device->dev);
|
||||
|
||||
if (count > sizeof(state->action) - 1)
|
||||
return -EINVAL;
|
||||
|
||||
strncpy(state->action, buf, sizeof(state->action) - 1);
|
||||
state->action[sizeof(state->action) - 1] = 0;
|
||||
|
||||
/* Strip newline if it exists */
|
||||
if (state->action[count - 1] == '\n')
|
||||
state->action[count - 1] = 0;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t entry_id_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct tegra_r2p_data *state = dev_get_drvdata(&r2p_device->dev);
|
||||
int res;
|
||||
|
||||
if (strlen(state->entry_id))
|
||||
res = sprintf(buf, "%s\n", state->entry_id);
|
||||
else
|
||||
res = sprintf(buf, "Not-set\n");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t entry_id_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
struct tegra_r2p_data *state = dev_get_drvdata(&r2p_device->dev);
|
||||
|
||||
if (count > sizeof(state->entry_id) - 1)
|
||||
return -EINVAL;
|
||||
|
||||
strncpy(state->entry_id, buf, sizeof(state->entry_id) - 1);
|
||||
state->entry_id[sizeof(state->entry_id) - 1] = 0;
|
||||
|
||||
/* Strip newline if it exists */
|
||||
if (state->entry_id[count - 1] == '\n')
|
||||
state->entry_id[count - 1] = 0;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t param1_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct tegra_r2p_data *state = dev_get_drvdata(&r2p_device->dev);
|
||||
|
||||
return sprintf(buf, "%d\n", (int)state->param1);
|
||||
}
|
||||
|
||||
static ssize_t param1_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
struct tegra_r2p_data *state = dev_get_drvdata(&r2p_device->dev);
|
||||
ssize_t res;
|
||||
long value;
|
||||
|
||||
res = kstrtol(buf, 0, &value);
|
||||
if (!res)
|
||||
state->param1 = value;
|
||||
|
||||
return res ? res : count;
|
||||
}
|
||||
|
||||
static ssize_t param2_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct tegra_r2p_data *state = dev_get_drvdata(&r2p_device->dev);
|
||||
|
||||
return sprintf(buf, "%d\n", (int)state->param2);
|
||||
}
|
||||
|
||||
static ssize_t param2_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
struct tegra_r2p_data *state = dev_get_drvdata(&r2p_device->dev);
|
||||
ssize_t res;
|
||||
long value;
|
||||
|
||||
res = kstrtol(buf, 0, &value);
|
||||
if (!res)
|
||||
state->param2 = value;
|
||||
|
||||
return res ? res : count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RW(action);
|
||||
static DEVICE_ATTR_RW(entry_id);
|
||||
static DEVICE_ATTR_RW(param1);
|
||||
static DEVICE_ATTR_RW(param2);
|
||||
|
||||
static struct attribute *r2p_sysfs_attrs[] = {
|
||||
&dev_attr_action.attr,
|
||||
&dev_attr_entry_id.attr,
|
||||
&dev_attr_param1.attr,
|
||||
&dev_attr_param2.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(r2p_sysfs);
|
||||
|
||||
static int tegra_r2p_driver_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct tegra_r2p_data *state;
|
||||
struct tegra_pmc *pmc;
|
||||
int err;
|
||||
|
||||
if (!enabled)
|
||||
return 0;
|
||||
|
||||
r2p_device = pdev;
|
||||
|
||||
state = devm_kzalloc(&pdev->dev, sizeof(struct tegra_r2p_data), GFP_KERNEL);
|
||||
|
||||
/* Use nvidia,pmc to specify */
|
||||
pmc = devm_tegra_pmc_get(&pdev->dev);
|
||||
if (IS_ERR(pmc)) {
|
||||
dev_err(&pdev->dev, "failed to get PMC\n");
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
/* Copy reboot action if valid */
|
||||
if (action) {
|
||||
strncpy(state->action, action, sizeof(state->action) - 1);
|
||||
state->action[sizeof(state->action) - 1] = 0;
|
||||
}
|
||||
|
||||
/* Copy entry ID if valid */
|
||||
if (entry_id) {
|
||||
strncpy(state->entry_id, entry_id, sizeof(state->entry_id) - 1);
|
||||
state->entry_id[sizeof(state->entry_id) - 1] = 0;
|
||||
}
|
||||
|
||||
/* Set reboot reason parameters. */
|
||||
state->param1 = param1;
|
||||
state->param2 = param2;
|
||||
|
||||
state->dev = &pdev->dev;
|
||||
state->pmc = pmc;
|
||||
|
||||
dev_set_drvdata(&pdev->dev, state);
|
||||
|
||||
err = sysfs_create_groups(&pdev->dev.kobj, r2p_sysfs_groups);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "sysfs creation failed\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
state->reboot_notifier.notifier_call = tegra_r2p_reboot_notify;
|
||||
err = devm_register_reboot_notifier(&pdev->dev,
|
||||
&state->reboot_notifier);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev,
|
||||
"unable to register reboot notifier, %d\n",
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id tegra_r2p_match[] = {
|
||||
{ .compatible = "nvidia,tegra124-r2p", },
|
||||
{ .compatible = "nvidia,tegra210-r2p", },
|
||||
{ .compatible = "nvidia,tegra210b01-r2p", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tegra_r2p_match);
|
||||
|
||||
static struct platform_driver tegra_r2p_driver = {
|
||||
.probe = tegra_r2p_driver_probe,
|
||||
.driver = {
|
||||
.name = "tegra-r2p",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = tegra_r2p_match
|
||||
},
|
||||
};
|
||||
|
||||
static int __init tegra_r2p_init(void)
|
||||
{
|
||||
return platform_driver_register(&tegra_r2p_driver);
|
||||
}
|
||||
core_initcall(tegra_r2p_init);
|
||||
|
||||
static void __exit tegra_r2p_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&tegra_r2p_driver);
|
||||
}
|
||||
module_exit(tegra_r2p_exit);
|
||||
|
||||
MODULE_AUTHOR("Thomas Makin <halorocker89@gmail.com>");
|
||||
MODULE_DESCRIPTION("Reboot2Payload driver for Tegra124/210/210b01");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
@@ -280,6 +280,15 @@
|
||||
#define MAX77620_CNFGBBC_RESISTOR_MASK 0xC0
|
||||
#define MAX77620_CNFGBBC_RESISTOR_SHIFT 6
|
||||
|
||||
#define MAX77620_IRQ_ONOFF_MRWRN_MASK BIT(0)
|
||||
#define MAX77620_IRQ_ONOFF_EN0_1SEC_MASK BIT(1)
|
||||
#define MAX77620_IRQ_ONOFF_EN0_F_MASK BIT(2)
|
||||
#define MAX77620_IRQ_ONOFF_EN0_R_MASK BIT(3)
|
||||
#define MAX77620_IRQ_ONOFF_LID_F_MASK BIT(4)
|
||||
#define MAX77620_IRQ_ONOFF_LID_R_MASK BIT(5)
|
||||
#define MAX77620_IRQ_ONOFF_ACOK_F_MASK BIT(6)
|
||||
#define MAX77620_IRQ_ONOFF_ACOK_R_MASK BIT(7)
|
||||
|
||||
#define MAX77620_FPS_COUNT 3
|
||||
|
||||
/* Interrupts */
|
||||
@@ -340,6 +349,7 @@ struct max77620_chip {
|
||||
|
||||
struct regmap_irq_chip_data *top_irq_data;
|
||||
struct regmap_irq_chip_data *gpio_irq_data;
|
||||
struct regmap_irq_chip_data *onoff_irq_data;
|
||||
};
|
||||
|
||||
#endif /* _MFD_MAX77620_H_ */
|
||||
@@ -149,6 +149,12 @@ enum tegra_io_pad {
|
||||
TEGRA_IO_PAD_AO_HV,
|
||||
};
|
||||
|
||||
struct tegra_br_cmd_cfg {
|
||||
u32 dev;
|
||||
u32 idx;
|
||||
u32 val;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SOC_TEGRA_PMC
|
||||
struct tegra_pmc *devm_tegra_pmc_get(struct device *dev);
|
||||
|
||||
@@ -156,6 +162,10 @@ int tegra_pmc_powergate_power_on(struct tegra_pmc *pmc, unsigned int id);
|
||||
int tegra_pmc_powergate_power_off(struct tegra_pmc *pmc, unsigned int id);
|
||||
int tegra_pmc_powergate_remove_clamping(struct tegra_pmc *pmc, unsigned int id);
|
||||
|
||||
int tegra_pmc_edit_bootrom_scratch_reset(struct tegra_pmc *pmc,
|
||||
struct tegra_br_cmd_cfg *bcfg, u32 bcfg_size);
|
||||
u32 tegra_pmc_readl(struct tegra_pmc *pmc, unsigned long offset);
|
||||
|
||||
/* Must be called with clk disabled, and returns with clk enabled */
|
||||
int tegra_pmc_powergate_sequence_power_up(struct tegra_pmc *pmc,
|
||||
unsigned int id, struct clk *clk,
|
||||
@@ -212,6 +222,19 @@ tegra_pmc_powergate_sequence_power_up(struct tegra_pmc *pmc, unsigned int id,
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int
|
||||
tegra_pmc_edit_bootrom_scratch_reset(struct tegra_pmc *pmc,
|
||||
struct tegra_br_cmd_cfg *bcfg, u32 bcfg_size)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline u32
|
||||
tegra_pmc_readl(struct tegra_pmc *pmc, unsigned long offset)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int
|
||||
tegra_pmc_io_pad_power_enable(struct tegra_pmc *pmc, enum tegra_io_pad id)
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user