mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 20:54:03 +02:00
reset: eyeq: Add EyeQ7H compatibles
Add support for the reset controllers found in the EyeQ7H OLB. For this, three new types of reset domain are added to the driver. The EQR_EYEQ7H_ACRP reset domain is similar to the EQR_EYEQ5_ACRP domain, sharing the same register address calculation but featuring a different register layout. When writing to the register, MBIST bits are set to zero to ensure normal device operation. The EQR_EYEQ7H_CFG reset domain is similar to the EQR_EYEQ5_PCIE domain, with two bits per device instead of one. These two bits, clock enable and nreset, are kept in sync when asserting and deasserting the device reset. The EQR_EYEQ7H_ACC reset domain is similar to the EQR_EYEQ6H_SARCR domain, with a different registers layout and no busy waiting. Alongside these new reset domains, add EQR_NB_DOM_TYPES at the end of the eqr_domain_type enumeration and use it to declare the eqr_timings array. This ensures that we have the expected number of entries when using the timings in eqr_busy_wait_locked(). Add and order the auxiliary_device_id entries in eqr_id_table. Originally-by: Sari Khoury <sari.khoury@mobileye.com> Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de> Acked-by: Philipp Zabel <p.zabel@pengutronix.de> Signed-off-by: Benoît Monin <benoit.monin@bootlin.com>
This commit is contained in:
parent
c74d7d8021
commit
379fc3b26b
|
|
@ -1,10 +1,11 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Reset driver for the Mobileye EyeQ5, EyeQ6L and EyeQ6H platforms.
|
||||
* Reset driver for the Mobileye EyeQ5, EyeQ6L, EyeQ6H and EyeQ7H platforms.
|
||||
*
|
||||
* Controllers live in a shared register region called OLB. EyeQ5 and EyeQ6L
|
||||
* have a single OLB instance for a single reset controller. EyeQ6H has seven
|
||||
* OLB instances; three host reset controllers.
|
||||
* OLB instances; three host reset controllers. EyeQ7H has fourteen OLB instances;
|
||||
* eleven host reset controllers.
|
||||
*
|
||||
* Each reset controller has one or more domain. Domains are of a given type
|
||||
* (see enum eqr_domain_type), with a valid offset mask (up to 32 resets per
|
||||
|
|
@ -73,6 +74,43 @@
|
|||
* 9. PMA0 10. PMA1 11. MPC0 12. MPC1
|
||||
* 13. MPC2 14. MPC3 15. PERIPH
|
||||
*
|
||||
* Known resets in EyeQ7H acc domain 0 (type EQR_EYEQ7H_ACRP)
|
||||
* 0. VMP0 1. XVMP1 2. VMP2 3. VMP3
|
||||
* 4. MPC0 5. MPC1 6. PMA0 7. PMA1
|
||||
*
|
||||
* Known resets in EyeQ7H acc domain 1 (type EQR_EYEQ7H_ACC)
|
||||
* 0. NCORE0 1. NCORE1 2. NCORE0_M 3. NCORE1_M
|
||||
* 4. NCORE_NOC 5. VMP_NOC 6. MPC_NOC 7. PMA_NOC
|
||||
*
|
||||
* Known resets in EyeQ7H ddr (type EQR_EYEQ7H_CFG)
|
||||
* 0. APB 1. DMI 2. DFI 3. PHY_SMS
|
||||
* 4. CTL_SMS
|
||||
*
|
||||
* Known resets in EyeQ7H east (type EQR_EYEQ7H_CFG)
|
||||
* 0. ISP 1. VEU 2. LBIST
|
||||
*
|
||||
* Known resets in EyeQ7H periph (type EQR_EYEQ6H_SARCR)
|
||||
* 0. gpio 1.EXT TIMER 2.UART 3. SPI
|
||||
* 4. I2C0 5. I2C1 6.I2C2 7. I2S
|
||||
*
|
||||
* Known resets in EyeQ7H south domain 0 (type EQR_EYEQ7H_CFG)
|
||||
* 0. PCI_PHY 1. PCI_CTL 2. S_NOC 3. GBE_PHY
|
||||
* 4. GBE_CTL
|
||||
*
|
||||
* Known resets in EyeQ7H south domain 1 (type EQR_EYEQ7H_CFG)
|
||||
* 0. XSPI 1. UFS 2. VDIO
|
||||
*
|
||||
* Known resets in EyeQ7H west (type EQR_EYEQ7H_CFG)
|
||||
* 0. GPU 1. CAU 2. LBIST 3. GPU_LBIST
|
||||
*
|
||||
* Known resets in EyeQ7H xnn domain 0 (type EQR_EYEQ7H_ACRP)
|
||||
* 0. XNN0 1. XNN1 2.XNN2
|
||||
*
|
||||
* Known resets in EyeQ7H xnn domain 1 (type EQR_EYEQ7H_ACC)
|
||||
* 0. XNN0 1. XNN1 2. XNN2 3. XNN3
|
||||
* 4. NCORE 5. L2_0 6. L2_1 7. SMS_0
|
||||
* 8. SMS_1
|
||||
*
|
||||
* Abbreviations:
|
||||
* - PMA: Programmable Macro Array
|
||||
* - MPC: Multi-threaded Processing Clusters
|
||||
|
|
@ -114,6 +152,11 @@ enum eqr_domain_type {
|
|||
EQR_EYEQ5_ACRP,
|
||||
EQR_EYEQ5_PCIE,
|
||||
EQR_EYEQ6H_SARCR,
|
||||
EQR_EYEQ7H_ACC,
|
||||
EQR_EYEQ7H_ACRP,
|
||||
EQR_EYEQ7H_CFG,
|
||||
|
||||
EQR_NB_DOM_TYPES /* number of domain types, keep at the end */
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -138,16 +181,34 @@ enum eqr_domain_type {
|
|||
#define EQR_EYEQ6H_SARCR_RST_STATUS (0x008)
|
||||
#define EQR_EYEQ6H_SARCR_CLK_REQUEST (0x00C)
|
||||
|
||||
/*
|
||||
* Domain type EQR_EYEQ7H_ACC register offsets.
|
||||
*/
|
||||
#define EQR_EYEQ7H_ACC_CLK_EN (0x000)
|
||||
#define EQR_EYEQ7H_ACC_RST_EN (0x004)
|
||||
|
||||
/*
|
||||
* Domain type EQR_EYEQ7H_ACRP register masks.
|
||||
* Registers are: base + 4 * offset.
|
||||
*/
|
||||
#define EQR_EYEQ7H_ACRP_PD_REQ BIT(0)
|
||||
#define EQR_EYEQ7H_ACRP_MBIST_CFG GENMASK(3, 1)
|
||||
#define EQR_EYEQ7H_ACRP_ST_POWER_DOWN BIT(13)
|
||||
#define EQR_EYEQ7H_ACRP_ST_ACTIVE BIT(14)
|
||||
|
||||
struct eqr_busy_wait_timings {
|
||||
unsigned long sleep_us;
|
||||
unsigned long timeout_us;
|
||||
};
|
||||
|
||||
static const struct eqr_busy_wait_timings eqr_timings[] = {
|
||||
static const struct eqr_busy_wait_timings eqr_timings[EQR_NB_DOM_TYPES] = {
|
||||
[EQR_EYEQ5_SARCR] = {1, 10},
|
||||
[EQR_EYEQ5_ACRP] = {1, 40 * USEC_PER_MSEC}, /* LBIST implies long timeout. */
|
||||
/* EQR_EYEQ5_PCIE does no busy waiting. */
|
||||
[EQR_EYEQ6H_SARCR] = {1, 400},
|
||||
/* EQR_EYEQ7H_ACC does no busy waiting. */
|
||||
[EQR_EYEQ7H_ACRP] = {1, 40 * USEC_PER_MSEC},
|
||||
/* EQR_EYEQ7H_CFG does no busy waiting. */
|
||||
};
|
||||
|
||||
#define EQR_MAX_DOMAIN_COUNT 3
|
||||
|
|
@ -221,10 +282,6 @@ static int eqr_busy_wait_locked(struct eqr_private *priv, struct device *dev,
|
|||
sleep_us, timeout_us);
|
||||
break;
|
||||
|
||||
case EQR_EYEQ5_PCIE:
|
||||
ret = 0; /* No busy waiting. */
|
||||
break;
|
||||
|
||||
case EQR_EYEQ6H_SARCR:
|
||||
/*
|
||||
* Wait until both bits change:
|
||||
|
|
@ -241,6 +298,23 @@ static int eqr_busy_wait_locked(struct eqr_private *priv, struct device *dev,
|
|||
&rst_status, &clk_status);
|
||||
break;
|
||||
|
||||
case EQR_EYEQ7H_ACRP:
|
||||
reg = base + 4 * offset;
|
||||
if (assert)
|
||||
mask = EQR_EYEQ7H_ACRP_ST_POWER_DOWN;
|
||||
else
|
||||
mask = EQR_EYEQ7H_ACRP_ST_ACTIVE;
|
||||
|
||||
ret = readl_poll_timeout(reg, val, !!(val & mask),
|
||||
sleep_us, timeout_us);
|
||||
break;
|
||||
|
||||
case EQR_EYEQ5_PCIE:
|
||||
case EQR_EYEQ7H_ACC:
|
||||
case EQR_EYEQ7H_CFG:
|
||||
ret = 0; /* No busy waiting. */
|
||||
break;
|
||||
|
||||
default:
|
||||
WARN_ON(1);
|
||||
ret = -EINVAL;
|
||||
|
|
@ -285,6 +359,28 @@ static void eqr_assert_locked(struct eqr_private *priv, u32 domain, u32 offset)
|
|||
writel(val, base + EQR_EYEQ6H_SARCR_CLK_REQUEST);
|
||||
break;
|
||||
|
||||
case EQR_EYEQ7H_ACC:
|
||||
/* RST_REQUEST and CLK_REQUEST must be kept in sync. */
|
||||
val = readl(base + EQR_EYEQ7H_ACC_RST_EN);
|
||||
val &= ~BIT(offset);
|
||||
writel(val, base + EQR_EYEQ7H_ACC_RST_EN);
|
||||
writel(val, base + EQR_EYEQ7H_ACC_CLK_EN);
|
||||
break;
|
||||
|
||||
case EQR_EYEQ7H_ACRP:
|
||||
/* set powerdown and leave MBIST bits at zero */
|
||||
reg = base + 4 * offset;
|
||||
val = readl(reg) & ~EQR_EYEQ7H_ACRP_MBIST_CFG;
|
||||
writel(val | EQR_EYEQ7H_ACRP_PD_REQ, reg);
|
||||
break;
|
||||
|
||||
case EQR_EYEQ7H_CFG:
|
||||
/* clear clock enable and NRESET bits */
|
||||
val = readl(base);
|
||||
val &= ~GENMASK(2 * offset + 1, 2 * offset);
|
||||
writel(val, base);
|
||||
break;
|
||||
|
||||
default:
|
||||
WARN_ON(1);
|
||||
break;
|
||||
|
|
@ -339,6 +435,28 @@ static void eqr_deassert_locked(struct eqr_private *priv, u32 domain,
|
|||
writel(val, base + EQR_EYEQ6H_SARCR_CLK_REQUEST);
|
||||
break;
|
||||
|
||||
case EQR_EYEQ7H_ACC:
|
||||
/* RST_REQUEST and CLK_REQUEST must be kept in sync. */
|
||||
val = readl(base + EQR_EYEQ7H_ACC_RST_EN);
|
||||
val |= BIT(offset);
|
||||
writel(val, base + EQR_EYEQ7H_ACC_RST_EN);
|
||||
writel(val, base + EQR_EYEQ7H_ACC_CLK_EN);
|
||||
break;
|
||||
|
||||
case EQR_EYEQ7H_ACRP:
|
||||
/* clear powerdown and leave MBIST bits at zero */
|
||||
reg = base + 4 * offset;
|
||||
val = readl(reg) & ~EQR_EYEQ7H_ACRP_MBIST_CFG;
|
||||
writel(val & ~EQR_EYEQ7H_ACRP_PD_REQ, reg);
|
||||
break;
|
||||
|
||||
case EQR_EYEQ7H_CFG:
|
||||
/* set clock enable and NRESET bits */
|
||||
val = readl(base);
|
||||
val |= GENMASK(2 * offset + 1, 2 * offset);
|
||||
writel(val, base);
|
||||
break;
|
||||
|
||||
default:
|
||||
WARN_ON(1);
|
||||
break;
|
||||
|
|
@ -385,6 +503,14 @@ static int eqr_status(struct reset_controller_dev *rcdev, unsigned long id)
|
|||
case EQR_EYEQ6H_SARCR:
|
||||
reg = base + EQR_EYEQ6H_SARCR_RST_STATUS;
|
||||
return !(readl(reg) & BIT(offset));
|
||||
case EQR_EYEQ7H_ACC:
|
||||
reg = base + EQR_EYEQ7H_ACC_RST_EN;
|
||||
return !(readl(reg) & BIT(offset));
|
||||
case EQR_EYEQ7H_ACRP:
|
||||
reg = base + 4 * offset;
|
||||
return !(readl(reg) & EQR_EYEQ7H_ACRP_ST_ACTIVE);
|
||||
case EQR_EYEQ7H_CFG:
|
||||
return !(readl(base) & BIT(2 * offset));
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -558,6 +684,113 @@ static const struct eqr_match_data eqr_eyeq6h_acc_data = {
|
|||
.domains = eqr_eyeq6h_acc_domains,
|
||||
};
|
||||
|
||||
static const struct eqr_domain_descriptor eqr_eyeq7h_acc_domains[] = {
|
||||
{
|
||||
.type = EQR_EYEQ7H_ACRP,
|
||||
.valid_mask = 0xFF,
|
||||
.offset = 0x000,
|
||||
},
|
||||
{
|
||||
.type = EQR_EYEQ7H_ACC,
|
||||
.valid_mask = 0xFF,
|
||||
.offset = 0x060,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct eqr_match_data eqr_eyeq7h_acc_data = {
|
||||
.domain_count = ARRAY_SIZE(eqr_eyeq7h_acc_domains),
|
||||
.domains = eqr_eyeq7h_acc_domains,
|
||||
};
|
||||
|
||||
static const struct eqr_domain_descriptor eqr_eyeq7h_ddr_domains[] = {
|
||||
{
|
||||
.type = EQR_EYEQ7H_CFG,
|
||||
.valid_mask = 0x1F,
|
||||
.offset = 0x008,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct eqr_match_data eqr_eyeq7h_ddr_data = {
|
||||
.domain_count = ARRAY_SIZE(eqr_eyeq7h_ddr_domains),
|
||||
.domains = eqr_eyeq7h_ddr_domains,
|
||||
};
|
||||
|
||||
static const struct eqr_domain_descriptor eqr_eyeq7h_east_domains[] = {
|
||||
{
|
||||
.type = EQR_EYEQ7H_CFG,
|
||||
.valid_mask = 0x7,
|
||||
.offset = 0x060,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct eqr_match_data eqr_eyeq7h_east_data = {
|
||||
.domain_count = ARRAY_SIZE(eqr_eyeq7h_east_domains),
|
||||
.domains = eqr_eyeq7h_east_domains,
|
||||
};
|
||||
|
||||
/* Periph OLBs each have an instance. */
|
||||
static const struct eqr_domain_descriptor eqr_eyeq7h_per_domains[] = {
|
||||
{
|
||||
.type = EQR_EYEQ6H_SARCR,
|
||||
.valid_mask = 0xFF,
|
||||
.offset = 0x030,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct eqr_match_data eqr_eyeq7h_per_data = {
|
||||
.domain_count = ARRAY_SIZE(eqr_eyeq7h_per_domains),
|
||||
.domains = eqr_eyeq7h_per_domains,
|
||||
};
|
||||
|
||||
static const struct eqr_domain_descriptor eqr_eyeq7h_south_domains[] = {
|
||||
{
|
||||
.type = EQR_EYEQ7H_CFG,
|
||||
.valid_mask = 0x1F,
|
||||
.offset = 0x070,
|
||||
},
|
||||
{
|
||||
.type = EQR_EYEQ7H_CFG,
|
||||
.valid_mask = 0x7,
|
||||
.offset = 0x074,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct eqr_match_data eqr_eyeq7h_south_data = {
|
||||
.domain_count = ARRAY_SIZE(eqr_eyeq7h_south_domains),
|
||||
.domains = eqr_eyeq7h_south_domains,
|
||||
};
|
||||
|
||||
static const struct eqr_domain_descriptor eqr_eyeq7h_west_domains[] = {
|
||||
{
|
||||
.type = EQR_EYEQ7H_CFG,
|
||||
.valid_mask = 0xf,
|
||||
.offset = 0x068,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct eqr_match_data eqr_eyeq7h_west_data = {
|
||||
.domain_count = ARRAY_SIZE(eqr_eyeq7h_west_domains),
|
||||
.domains = eqr_eyeq7h_west_domains,
|
||||
};
|
||||
|
||||
static const struct eqr_domain_descriptor eqr_eyeq7h_xnn_domains[] = {
|
||||
{
|
||||
.type = EQR_EYEQ7H_ACRP,
|
||||
.valid_mask = 0x7,
|
||||
.offset = 0x000,
|
||||
},
|
||||
{
|
||||
.type = EQR_EYEQ7H_ACC,
|
||||
.valid_mask = 0x1FF,
|
||||
.offset = 0x060,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct eqr_match_data eqr_eyeq7h_xnn_data = {
|
||||
.domain_count = ARRAY_SIZE(eqr_eyeq7h_xnn_domains),
|
||||
.domains = eqr_eyeq7h_xnn_domains,
|
||||
};
|
||||
|
||||
/*
|
||||
* Table describes OLB system-controller compatibles.
|
||||
* It does not get used to match against devicetree node.
|
||||
|
|
@ -569,15 +802,35 @@ static const struct of_device_id eqr_match_table[] = {
|
|||
{ .compatible = "mobileye,eyeq6h-west-olb", .data = &eqr_eyeq6h_we_data },
|
||||
{ .compatible = "mobileye,eyeq6h-east-olb", .data = &eqr_eyeq6h_we_data },
|
||||
{ .compatible = "mobileye,eyeq6h-acc-olb", .data = &eqr_eyeq6h_acc_data },
|
||||
{ .compatible = "mobileye,eyeq7h-acc0-olb", .data = &eqr_eyeq7h_acc_data },
|
||||
{ .compatible = "mobileye,eyeq7h-acc1-olb", .data = &eqr_eyeq7h_acc_data },
|
||||
{ .compatible = "mobileye,eyeq7h-ddr0-olb", .data = &eqr_eyeq7h_ddr_data },
|
||||
{ .compatible = "mobileye,eyeq7h-ddr1-olb", .data = &eqr_eyeq7h_ddr_data },
|
||||
{ .compatible = "mobileye,eyeq7h-east-olb", .data = &eqr_eyeq7h_east_data },
|
||||
{ .compatible = "mobileye,eyeq7h-periph-east-olb", .data = &eqr_eyeq7h_per_data },
|
||||
{ .compatible = "mobileye,eyeq7h-periph-west-olb", .data = &eqr_eyeq7h_per_data },
|
||||
{ .compatible = "mobileye,eyeq7h-south-olb", .data = &eqr_eyeq7h_south_data },
|
||||
{ .compatible = "mobileye,eyeq7h-west-olb", .data = &eqr_eyeq7h_west_data },
|
||||
{ .compatible = "mobileye,eyeq7h-xnn0-olb", .data = &eqr_eyeq7h_xnn_data },
|
||||
{ .compatible = "mobileye,eyeq7h-xnn1-olb", .data = &eqr_eyeq7h_xnn_data },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, eqr_match_table);
|
||||
|
||||
static const struct auxiliary_device_id eqr_id_table[] = {
|
||||
{ .name = "clk_eyeq.reset" },
|
||||
{ .name = "clk_eyeq.reset_west" },
|
||||
{ .name = "clk_eyeq.reset_east" },
|
||||
{ .name = "clk_eyeq.reset_acc" },
|
||||
{ .name = "clk_eyeq.reset_acc0" },
|
||||
{ .name = "clk_eyeq.reset_acc1" },
|
||||
{ .name = "clk_eyeq.reset_ddr0" },
|
||||
{ .name = "clk_eyeq.reset_ddr1" },
|
||||
{ .name = "clk_eyeq.reset_east" },
|
||||
{ .name = "clk_eyeq.reset_periph_east" },
|
||||
{ .name = "clk_eyeq.reset_periph_west" },
|
||||
{ .name = "clk_eyeq.reset_south" },
|
||||
{ .name = "clk_eyeq.reset_west" },
|
||||
{ .name = "clk_eyeq.reset_xnn0" },
|
||||
{ .name = "clk_eyeq.reset_xnn1" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(auxiliary, eqr_id_table);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user