soc: tegra: add support for brom cmds
Tegra bootrom can signal PMIC and other onboard devices to handle early-boot configuration. Downstream L4T kernel has long supported this functionality, where commands are specified via device-tree and can be hooked for power/reset events. Based on: - https://gitlab.com/nvidia/nv-tegra/linux-3.10/-/commit/4ac6f24c8988ef8f6d8100f9dceede5a3ff4a2d3 - https://gitlab.com/nvidia/nv-tegra/linux-4.4/-/commit/5ba61fa064fdd66c8e84592e721a5ac0fa78ed6e - https://github.com/CTCaer/switch-l4t-kernel-4.9/commit/b4f03b6ab671597971bd9fc41482c0b52eb64bfd Co-developed-by: Laxman Dewangan <ldewangan@nvidia.com> Co-developed-by: CTCaer <ctcaer@gmail.com>
This commit is contained in:
1 parent
33b21c2d6c
commit
baccdc9e58
2 files changed
+400
-19
No files matched your search
+377
-19
@@ -180,6 +180,26 @@
|
|||||||
#define PMC_UTMIP_PAD_CFG0 0x4c0
|
#define PMC_UTMIP_PAD_CFG0 0x4c0
|
||||||
#define PMC_UTMIP_UHSIC_SLEEP_CFG1 0x4d0
|
#define PMC_UTMIP_UHSIC_SLEEP_CFG1 0x4d0
|
||||||
#define PMC_UTMIP_SLEEPWALK_P3 0x4e0
|
#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 */
|
/* Tegra186 and later */
|
||||||
#define WAKE_AOWAKE_CNTRL(x) (0x000 + ((x) << 2))
|
#define WAKE_AOWAKE_CNTRL(x) (0x000 + ((x) << 2))
|
||||||
#define WAKE_AOWAKE_CNTRL_LEVEL (1 << 3)
|
#define WAKE_AOWAKE_CNTRL_LEVEL (1 << 3)
|
||||||
@@ -295,6 +315,29 @@ struct tegra_powergate {
|
|||||||
struct reset_control *reset;
|
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 {
|
struct tegra_io_pad_soc {
|
||||||
enum tegra_io_pad id;
|
enum tegra_io_pad id;
|
||||||
unsigned int dpd;
|
unsigned int dpd;
|
||||||
@@ -381,6 +424,7 @@ struct tegra_pmc_soc {
|
|||||||
bool needs_mbist_war;
|
bool needs_mbist_war;
|
||||||
bool has_io_pad_wren;
|
bool has_io_pad_wren;
|
||||||
bool maybe_tz_only;
|
bool maybe_tz_only;
|
||||||
|
bool has_bootrom_command;
|
||||||
|
|
||||||
const struct tegra_io_pad_soc *io_pads;
|
const struct tegra_io_pad_soc *io_pads;
|
||||||
unsigned int num_io_pads;
|
unsigned int num_io_pads;
|
||||||
@@ -1322,25 +1366,6 @@ static int tegra_pmc_panic_handler(struct notifier_block *this,
|
|||||||
return NOTIFY_DONE;
|
return NOTIFY_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tegra_pmc_power_off_handler(struct sys_off_data *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);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NOTIFY_DONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int powergate_show(struct seq_file *s, void *data)
|
static int powergate_show(struct seq_file *s, void *data)
|
||||||
{
|
{
|
||||||
struct tegra_pmc *pmc = data;
|
struct tegra_pmc *pmc = data;
|
||||||
@@ -1710,6 +1735,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 *
|
static const struct tegra_io_pad_soc *
|
||||||
tegra_io_pad_find(struct tegra_pmc *pmc, enum tegra_io_pad id)
|
tegra_io_pad_find(struct tegra_pmc *pmc, enum tegra_io_pad id)
|
||||||
{
|
{
|
||||||
@@ -3194,6 +3543,9 @@ static int tegra_pmc_probe(struct platform_device *pdev)
|
|||||||
return dev_err_probe(&pdev->dev, PTR_ERR(pmc->clk),
|
return dev_err_probe(&pdev->dev, PTR_ERR(pmc->clk),
|
||||||
"failed to get pclk\n");
|
"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
|
* PMC should be last resort for restarting since it soft-resets
|
||||||
* CPU without resetting everything else.
|
* CPU without resetting everything else.
|
||||||
@@ -3592,6 +3944,7 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = {
|
|||||||
.has_blink_output = true,
|
.has_blink_output = true,
|
||||||
.has_usb_sleepwalk = true,
|
.has_usb_sleepwalk = true,
|
||||||
.has_single_mmio_aperture = true,
|
.has_single_mmio_aperture = true,
|
||||||
|
.has_bootrom_command = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char * const tegra30_powergates[] = {
|
static const char * const tegra30_powergates[] = {
|
||||||
@@ -3654,6 +4007,7 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = {
|
|||||||
.has_blink_output = true,
|
.has_blink_output = true,
|
||||||
.has_usb_sleepwalk = true,
|
.has_usb_sleepwalk = true,
|
||||||
.has_single_mmio_aperture = true,
|
.has_single_mmio_aperture = true,
|
||||||
|
.has_bootrom_command = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char * const tegra114_powergates[] = {
|
static const char * const tegra114_powergates[] = {
|
||||||
@@ -3712,6 +4066,7 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = {
|
|||||||
.has_blink_output = true,
|
.has_blink_output = true,
|
||||||
.has_usb_sleepwalk = true,
|
.has_usb_sleepwalk = true,
|
||||||
.has_single_mmio_aperture = true,
|
.has_single_mmio_aperture = true,
|
||||||
|
.has_bootrom_command = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char * const tegra124_powergates[] = {
|
static const char * const tegra124_powergates[] = {
|
||||||
@@ -3864,6 +4219,7 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = {
|
|||||||
.has_blink_output = true,
|
.has_blink_output = true,
|
||||||
.has_usb_sleepwalk = true,
|
.has_usb_sleepwalk = true,
|
||||||
.has_single_mmio_aperture = true,
|
.has_single_mmio_aperture = true,
|
||||||
|
.has_bootrom_command = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char * const tegra210_powergates[] = {
|
static const char * const tegra210_powergates[] = {
|
||||||
@@ -4045,6 +4401,7 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = {
|
|||||||
.has_usb_sleepwalk = true,
|
.has_usb_sleepwalk = true,
|
||||||
.has_single_mmio_aperture = true,
|
.has_single_mmio_aperture = true,
|
||||||
.has_panic_notifier = true,
|
.has_panic_notifier = true,
|
||||||
|
.has_bootrom_command = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char * const tegra210b01_powergates[] = {
|
static const char * const tegra210b01_powergates[] = {
|
||||||
@@ -4107,6 +4464,7 @@ static const struct tegra_pmc_soc tegra210b01_pmc_soc = {
|
|||||||
.has_usb_sleepwalk = true,
|
.has_usb_sleepwalk = true,
|
||||||
.has_single_mmio_aperture = true,
|
.has_single_mmio_aperture = true,
|
||||||
.has_panic_notifier = true,
|
.has_panic_notifier = true,
|
||||||
|
.has_bootrom_command = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct tegra_io_pad_soc tegra186_io_pads[] = {
|
static const struct tegra_io_pad_soc tegra186_io_pads[] = {
|
||||||
|
|||||||
@@ -149,6 +149,12 @@ enum tegra_io_pad {
|
|||||||
TEGRA_IO_PAD_AO_HV,
|
TEGRA_IO_PAD_AO_HV,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct tegra_br_cmd_cfg {
|
||||||
|
u32 dev;
|
||||||
|
u32 idx;
|
||||||
|
u32 val;
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_SOC_TEGRA_PMC
|
#ifdef CONFIG_SOC_TEGRA_PMC
|
||||||
struct tegra_pmc *devm_tegra_pmc_get(struct device *dev);
|
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_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_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 */
|
/* Must be called with clk disabled, and returns with clk enabled */
|
||||||
int tegra_pmc_powergate_sequence_power_up(struct tegra_pmc *pmc,
|
int tegra_pmc_powergate_sequence_power_up(struct tegra_pmc *pmc,
|
||||||
unsigned int id, struct clk *clk,
|
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;
|
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
|
static inline int
|
||||||
tegra_pmc_io_pad_power_enable(struct tegra_pmc *pmc, enum tegra_io_pad id)
|
tegra_pmc_io_pad_power_enable(struct tegra_pmc *pmc, enum tegra_io_pad id)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in new issue
Block a user