Skip to content

Commit

Permalink
Merge tag 'imx-drivers-5.1' of git://git.kernel.org/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/git/shawnguo/linux into arm/drivers

i.MX drivers update for 5.1:
 - Do not get GPCv2 driver depend on SOC_IMX8MQ since the driver is
   going to be used on more SoCs than just i.MX8MQ.
 - Add power domain information into SCU bindings document.
 - Add support of start/stop a CPU into imx firmware driver.
 - Support multiple address ranges per child node for imx-weim bus
   driver.

* tag 'imx-drivers-5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux:
  firmware: imx: Add support to start/stop a CPU
  soc: imx: Break dependency on SOC_IMX8MQ for GPCv2
  firmware: imx: scu-pd: add fallback compatible string support
  dt-bindings: fsl: scu: add imx8qm scu power domain support
  dt-bindings: fsl: scu: add fallback compatible string for power domain
  bus: imx-weim: guard against timing configuration conflicts
  bus: imx-weim: support multiple address ranges per child node
  dt-bindings: bus: imx-weim: document multiple address ranges per child node
  soc: imx: gpcv2: handle reset clocks
  soc: imx: gpcv2: handle additional power-down bits in handshake register

Signed-off-by: Arnd Bergmann <[email protected]>
  • Loading branch information
arndb committed Feb 15, 2019
2 parents 59f527d + d90bf29 commit c9235d9
Show file tree
Hide file tree
Showing 9 changed files with 212 additions and 21 deletions.
8 changes: 6 additions & 2 deletions Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,11 @@ This binding for the SCU power domain providers uses the generic power
domain binding[2].

Required properties:
- compatible: Should be "fsl,imx8qxp-scu-pd".
- compatible: Should be one of:
"fsl,imx8qm-scu-pd",
"fsl,imx8qxp-scu-pd"
followed by "fsl,scu-pd"

- #power-domain-cells: Must be 1. Contains the Resource ID used by
SCU commands.
See detailed Resource ID list from:
Expand Down Expand Up @@ -154,7 +158,7 @@ firmware {
};

pd: imx8qx-pd {
compatible = "fsl,imx8qxp-scu-pd";
compatible = "fsl,imx8qxp-scu-pd", "fsl,scu-pd";
#power-domain-cells = <1>;
};

Expand Down
32 changes: 29 additions & 3 deletions Documentation/devicetree/bindings/bus/imx-weim.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ Optional properties:
Timing property for child nodes. It is mandatory, not optional.

- fsl,weim-cs-timing: The timing array, contains timing values for the
child node. We can get the CS index from the child
node's "reg" property. The number of registers depends
on the selected chip.
child node. We get the CS indexes from the address
ranges in the child node's "reg" property.
The number of registers depends on the selected chip:
For i.MX1, i.MX21 ("fsl,imx1-weim") there are two
registers: CSxU, CSxL.
For i.MX25, i.MX27, i.MX31 and i.MX35 ("fsl,imx27-weim")
Expand Down Expand Up @@ -80,3 +80,29 @@ Example for an imx6q-sabreauto board, the NOR flash connected to the WEIM:
0x0000c000 0x1404a38e 0x00000000>;
};
};

Example for an imx6q-based board, a multi-chipselect device connected to WEIM:

In this case, both chip select 0 and 1 will be configured with the same timing
array values.

weim: weim@21b8000 {
compatible = "fsl,imx6q-weim";
reg = <0x021b8000 0x4000>;
clocks = <&clks 196>;
#address-cells = <2>;
#size-cells = <1>;
ranges = <0 0 0x08000000 0x02000000
1 0 0x0a000000 0x02000000
2 0 0x0c000000 0x02000000
3 0 0x0e000000 0x02000000>;
fsl,weim-cs-gpr = <&gpr>;

acme@0 {
compatible = "acme,whatever";
reg = <0 0 0x100>, <0 0x400000 0x800>,
<1 0x400000 0x800>;
fsl,weim-cs-timing = <0x024400b1 0x00001010 0x20081100
0x00000000 0xa0000240 0x00000000>;
};
};
3 changes: 3 additions & 0 deletions Documentation/devicetree/bindings/power/fsl,imx-gpcv2.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ Required properties:
Optional properties:

- power-supply: Power supply used to power the domain
- clocks: a number of phandles to clocks that need to be enabled during
domain power-up sequencing to ensure reset propagation into devices
located inside this power domain

Example:

Expand Down
70 changes: 57 additions & 13 deletions drivers/bus/imx-weim.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,17 @@ static const struct imx_weim_devtype imx51_weim_devtype = {
};

#define MAX_CS_REGS_COUNT 6
#define MAX_CS_COUNT 6
#define OF_REG_SIZE 3

struct cs_timing {
bool is_applied;
u32 regs[MAX_CS_REGS_COUNT];
};

struct cs_timing_state {
struct cs_timing cs[MAX_CS_COUNT];
};

static const struct of_device_id weim_id_table[] = {
/* i.MX1/21 */
Expand Down Expand Up @@ -111,31 +122,63 @@ static int __init imx_weim_gpr_setup(struct platform_device *pdev)
}

/* Parse and set the timing for this device. */
static int __init weim_timing_setup(struct device_node *np, void __iomem *base,
const struct imx_weim_devtype *devtype)
static int __init weim_timing_setup(struct device *dev,
struct device_node *np, void __iomem *base,
const struct imx_weim_devtype *devtype,
struct cs_timing_state *ts)
{
u32 cs_idx, value[MAX_CS_REGS_COUNT];
int i, ret;
int reg_idx, num_regs;
struct cs_timing *cst;

if (WARN_ON(devtype->cs_regs_count > MAX_CS_REGS_COUNT))
return -EINVAL;

/* get the CS index from this child node's "reg" property. */
ret = of_property_read_u32(np, "reg", &cs_idx);
if (ret)
return ret;

if (cs_idx >= devtype->cs_count)
if (WARN_ON(devtype->cs_count > MAX_CS_COUNT))
return -EINVAL;

ret = of_property_read_u32_array(np, "fsl,weim-cs-timing",
value, devtype->cs_regs_count);
if (ret)
return ret;

/* set the timing for WEIM */
for (i = 0; i < devtype->cs_regs_count; i++)
writel(value[i], base + cs_idx * devtype->cs_stride + i * 4);
/*
* the child node's "reg" property may contain multiple address ranges,
* extract the chip select for each.
*/
num_regs = of_property_count_elems_of_size(np, "reg", OF_REG_SIZE);
if (num_regs < 0)
return num_regs;
if (!num_regs)
return -EINVAL;
for (reg_idx = 0; reg_idx < num_regs; reg_idx++) {
/* get the CS index from this child node's "reg" property. */
ret = of_property_read_u32_index(np, "reg",
reg_idx * OF_REG_SIZE, &cs_idx);
if (ret)
break;

if (cs_idx >= devtype->cs_count)
return -EINVAL;

/* prevent re-configuring a CS that's already been configured */
cst = &ts->cs[cs_idx];
if (cst->is_applied && memcmp(value, cst->regs,
devtype->cs_regs_count * sizeof(u32))) {
dev_err(dev, "fsl,weim-cs-timing conflict on %pOF", np);
return -EINVAL;
}

/* set the timing for WEIM */
for (i = 0; i < devtype->cs_regs_count; i++)
writel(value[i],
base + cs_idx * devtype->cs_stride + i * 4);
if (!cst->is_applied) {
cst->is_applied = true;
memcpy(cst->regs, value,
devtype->cs_regs_count * sizeof(u32));
}
}

return 0;
}
Expand All @@ -148,6 +191,7 @@ static int __init weim_parse_dt(struct platform_device *pdev,
const struct imx_weim_devtype *devtype = of_id->data;
struct device_node *child;
int ret, have_child = 0;
struct cs_timing_state ts = {};

if (devtype == &imx50_weim_devtype) {
ret = imx_weim_gpr_setup(pdev);
Expand All @@ -156,7 +200,7 @@ static int __init weim_parse_dt(struct platform_device *pdev,
}

for_each_available_child_of_node(pdev->dev.of_node, child) {
ret = weim_timing_setup(child, base, devtype);
ret = weim_timing_setup(&pdev->dev, child, base, devtype, &ts);
if (ret)
dev_warn(&pdev->dev, "%pOF set timing failed.\n",
child);
Expand Down
38 changes: 38 additions & 0 deletions drivers/firmware/imx/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ struct imx_sc_msg_req_misc_set_ctrl {
u16 resource;
} __packed;

struct imx_sc_msg_req_cpu_start {
struct imx_sc_rpc_msg hdr;
u32 address_hi;
u32 address_lo;
u16 resource;
u8 enable;
} __packed;

struct imx_sc_msg_req_misc_get_ctrl {
struct imx_sc_rpc_msg hdr;
u32 ctrl;
Expand Down Expand Up @@ -97,3 +105,33 @@ int imx_sc_misc_get_control(struct imx_sc_ipc *ipc, u32 resource,
return 0;
}
EXPORT_SYMBOL(imx_sc_misc_get_control);

/*
* This function starts/stops a CPU identified by @resource
*
* @param[in] ipc IPC handle
* @param[in] resource resource the control is associated with
* @param[in] enable true for start, false for stop
* @param[in] phys_addr initial instruction address to be executed
*
* @return Returns 0 for success and < 0 for errors.
*/
int imx_sc_pm_cpu_start(struct imx_sc_ipc *ipc, u32 resource,
bool enable, u64 phys_addr)
{
struct imx_sc_msg_req_cpu_start msg;
struct imx_sc_rpc_msg *hdr = &msg.hdr;

hdr->ver = IMX_SC_RPC_VERSION;
hdr->svc = IMX_SC_RPC_SVC_PM;
hdr->func = IMX_SC_PM_FUNC_CPU_START;
hdr->size = 4;

msg.address_hi = phys_addr >> 32;
msg.address_lo = phys_addr;
msg.resource = resource;
msg.enable = enable;

return imx_scu_call_rpc(ipc, &msg, true);
}
EXPORT_SYMBOL(imx_sc_pm_cpu_start);
1 change: 1 addition & 0 deletions drivers/firmware/imx/scu-pd.c
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ static int imx_sc_pd_probe(struct platform_device *pdev)

static const struct of_device_id imx_sc_pd_match[] = {
{ .compatible = "fsl,imx8qxp-scu-pd", &imx8qxp_scu_pd},
{ .compatible = "fsl,scu-pd", &imx8qxp_scu_pd},
{ /* sentinel */ }
};

Expand Down
2 changes: 1 addition & 1 deletion drivers/soc/imx/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ menu "i.MX SoC drivers"

config IMX_GPCV2_PM_DOMAINS
bool "i.MX GPCv2 PM domains"
depends on SOC_IMX7D || SOC_IMX8MQ || (COMPILE_TEST && OF)
depends on ARCH_MXC || (COMPILE_TEST && OF)
depends on PM
select PM_GENERIC_DOMAINS
default y if SOC_IMX7D
Expand Down
Loading

0 comments on commit c9235d9

Please sign in to comment.