spmi: pmic-arb: Add support for PMIC v7
Subsystems (3)
v5 cover spmi: pmic-arb: Add support for PMIC v7
Hello,
The is version 5 of support for PMIC v7. I have added a new property qcom,bus-id for supporting v7 and then add driver changes for v7
Changes since v4:
- Fix David name and email
- remove trailing line in binding
Changes since v3:
- rebase on spmi/next
David Collins (1):
spmi: pmic-arb: Add support for PMIC v7
Vinod Koul (1):
dt-bindings: spmi: Add qcom,bus-id
.../bindings/spmi/qcom,spmi-pmic-arb.yaml | 10 + drivers/spmi/spmi-pmic-arb.c | 242 ++++++++++++++++-- 2 files changed, 231 insertions(+), 21 deletions(-)
base-commit: 18c42f8d23426d3f4048df89523aa47203c3493a
Signature · 1 line
2.37.3
PATCH v5 1/2 dt-bindings: spmi: Add qcom,bus-id
For PMIC arbiter version 7 and beyond we need to define if we are using primary or secondary bus, so add a new property of qcom,bus-id
--- .../devicetree/bindings/spmi/qcom,spmi-pmic-arb.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+)
Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.yaml +10 -0
@@ -85,6 +85,14 @@ properties: description: > which of the PMIC Arb provided channels to use for accesses + qcom,bus-id: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 1 + description: > + SPMI bus instance. only applicable to PMIC arbiter version 7 and beyond. + Supported values, 0 = primary bus, 1 = secondary bus + required: - compatible - reg-names
@@ -113,5 +121,7 @@ examples: interrupt-controller; #interrupt-cells = <4>; + + qcom,bus-id = <0>; };
Signature · 1 line
2.37.3
Re: [PATCH v5 1/2] dt-bindings: spmi: Add qcom,bus-id
Quoted 9 lines · Vinod Koul
For PMIC arbiter version 7 and beyond we need to define if we are using primary or secondary bus, so add a new property of qcom,bus-id
Signed-off-by Vinod Koul <[email protected]>Acked-by Rob Herring <[email protected]>--- .../devicetree/bindings/spmi/qcom,spmi-pmic-arb.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+)
My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check' on your patch (DT_CHECKER_FLAGS is new in v5.13):
yamllint warnings/errors:
dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/st,stm32-dmamux.example.dtb: dma-router@40020800: dma-masters:0: [4294967295, 4294967295] is too long
From schema: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/st,stm32-dmamux.yaml
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/st,stm32-dmamux.example.dtb: dma-router@40020800: Unevaluated properties are not allowed ('dma-channels', 'dma-masters', 'dma-requests' were unexpected)
From schema: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/st,stm32-dmamux.yaml
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/st,stm32-dmamux.example.dtb: dma-router@40020800: dma-masters:0: [4294967295, 4294967295] is too long
From schema: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/dma-router.yaml
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/renesas,rzn1-dmamux.example.dtb: dma-router@a0: dma-masters:0: [4294967295, 4294967295] is too long
From schema: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/dma-router.yaml
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/renesas,rzn1-dmamux.example.dtb: dma-router@a0: dma-masters:0: [4294967295, 4294967295] is too long
From schema: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/renesas,rzn1-dmamux.yaml
doc reference errors (make refcheckdocs):
See https://patchwork.ozlabs.org/patch/
This check can fail if there are any dependencies. The base for a patch series is generally the most recent rc1.
If you already ran 'make dt_binding_check' and didn't see the above error(s), then make sure 'yamllint' is installed and dt-schema is up to date:
pip3 install dtschema --upgrade
Please check and re-submit.
Rob Herring
maintainerRe: [PATCH v5 1/2] dt-bindings: spmi: Add qcom,bus-id
Quoted 16 lines · Krzysztof Kozlowski
Quoted 9 lines · Vinod Koul
For PMIC arbiter version 7 and beyond we need to define if we are using primary or secondary bus, so add a new property of qcom,bus-id
Signed-off-by Vinod Koul <[email protected]>Acked-by Rob Herring <[email protected]>--- .../devicetree/bindings/spmi/qcom,spmi-pmic-arb.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+)My bot found errors running 'make DT_CHECKER_FLAGS=-m
dt_binding_check' on your patch (DT_CHECKER_FLAGSis new in v5.13):yamllint warnings/errors:
Quoted 11 lines
dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/st,stm32-dmamux.example.dtb: dma-router@40020800: dma-masters:0: [4294967295, 4294967295] is too long
From schema: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/st,stm32-dmamux.yaml
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/st,stm32-dmamux.example.dtb: dma-router@40020800: Unevaluated properties are not allowed ('dma-channels', 'dma-masters', 'dma-requests' were unexpected)
From schema: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/st,stm32-dmamux.yaml
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/st,stm32-dmamux.example.dtb: dma-router@40020800: dma-masters:0: [4294967295, 4294967295] is too long
From schema: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/dma-router.yaml
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/renesas,rzn1-dmamux.example.dtb: dma-router@a0: dma-masters:0: [4294967295, 4294967295] is too long
From schema: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/dma-router.yaml
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/renesas,rzn1-dmamux.example.dtb: dma-router@a0: dma-masters:0: [4294967295, 4294967295] is too long
From schema: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/renesas,rzn1-dmamux.yaml
Ignore this. Unrelated.
Rob
Re: [PATCH v5 1/2] dt-bindings: spmi: Add qcom,bus-id
Quoted 29 lines · Rob Herring
Quoted 16 lines · Krzysztof Kozlowski
Quoted 9 lines · Vinod Koul
For PMIC arbiter version 7 and beyond we need to define if we are using primary or secondary bus, so add a new property of qcom,bus-id
Signed-off-by Vinod Koul <[email protected]>Acked-by Rob Herring <[email protected]>--- .../devicetree/bindings/spmi/qcom,spmi-pmic-arb.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+)My bot found errors running 'make DT_CHECKER_FLAGS=-m
dt_binding_check' on your patch (DT_CHECKER_FLAGSis new in v5.13):yamllint warnings/errors:
Quoted 11 lines
dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/st,stm32-dmamux.example.dtb: dma-router@40020800: dma-masters:0: [4294967295, 4294967295] is too long
From schema: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/st,stm32-dmamux.yaml
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/st,stm32-dmamux.example.dtb: dma-router@40020800: Unevaluated properties are not allowed ('dma-channels', 'dma-masters', 'dma-requests' were unexpected)
From schema: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/st,stm32-dmamux.yaml
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/st,stm32-dmamux.example.dtb: dma-router@40020800: dma-masters:0: [4294967295, 4294967295] is too long
From schema: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/dma-router.yaml
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/renesas,rzn1-dmamux.example.dtb: dma-router@a0: dma-masters:0: [4294967295, 4294967295] is too long
From schema: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/dma-router.yaml
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/renesas,rzn1-dmamux.example.dtb: dma-router@a0: dma-masters:0: [4294967295, 4294967295] is too long
From schema: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/renesas,rzn1-dmamux.yaml
Quoted 1 line
Ignore this. Unrelated.
Right!
Signature · 1 line
~Vinod
Re: [PATCH v5 1/2] dt-bindings: spmi: Add qcom,bus-id
In reply to Vinod KoulQuoted 5 lines · Vinod Koul
For PMIC arbiter version 7 and beyond we need to define if we are using primary or secondary bus, so add a new property of qcom,bus-id
Signed-off-by Vinod Koul <[email protected]>Acked-by Rob Herring <[email protected]>
Quoted 34 lines
--- .../devicetree/bindings/spmi/qcom,spmi-pmic-arb.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+)Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.yaml +10
-0@@ -85,6 +85,14 @@ properties: description: > which of the PMIC Arb provided channels to use for accesses + qcom,bus-id: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 1 + description: > + SPMI bus instance. only applicable to PMIC arbiter version 7 and beyond. + Supported values, 0 = primary bus, 1 = secondary bus + required: - compatible - reg-names@@ -113,5 +121,7 @@ examples: interrupt-controller; #interrupt-cells = <4>; + + qcom,bus-id = <0>; };Signature · 1 line
2.37.3
PATCH v5 2/2 spmi: pmic-arb: Add support for PMIC v7
In reply to Vinod KoulFrom: David Collins <[email protected]>
PMIC v7 has different offset values and seqeunces, so add support for this new version of PMIC
--- drivers/spmi/spmi-pmic-arb.c | 242 ++++++++++++++++++++++++++++++++--- 1 file changed, 221 insertions(+), 21 deletions(-)
drivers/spmi/spmi-pmic-arb.c +221 -21
@@ -22,8 +22,14 @@#define PMIC_ARB_VERSION_V2_MIN 0x20010000#define PMIC_ARB_VERSION_V3_MIN 0x30000000#define PMIC_ARB_VERSION_V5_MIN 0x50000000 +#define PMIC_ARB_VERSION_V7_MIN 0x70000000#define PMIC_ARB_INT_EN 0x0004 +#define PMIC_ARB_FEATURES 0x0004 +#define PMIC_ARB_FEATURES_PERIPH_MASK GENMASK(10, 0) + +#define PMIC_ARB_FEATURES1 0x0008 +/* PMIC Arbiter channel registers offsets */ #define PMIC_ARB_CMD 0x00#define PMIC_ARB_CONFIG 0x04
@@ -48,7 +54,6 @@#define INVALID_EE 0xFF/* Ownership Table */ -#define SPMI_OWNERSHIP_TABLE_REG (N ) (0x0700 + (4 * (N)))#define SPMI_OWNERSHIP_PERIPH2OWNER (X ) ((X) & 0x7)/* Channel Status fields */
@@ -91,6 +96,7 @@ enum pmic_arb_channel {/* Maximum number of support PMIC peripherals */ #define PMIC_ARB_MAX_PERIPHS 512 +#define PMIC_ARB_MAX_PERIPHS_V7 1024#define PMIC_ARB_TIMEOUT_US 1000#define PMIC_ARB_MAX_TRANS_BYTES (8)
@@ -104,12 +110,12 @@ enum pmic_arb_channel { ((((slave_id) &0xF ) <<28 ) | \ (((periph_id) &0xFF ) <<20 ) | \ (((irq_id) &0x7 ) <<16 ) | \ - (((apid) & 0x1FF) << 0)) + (((apid) & 0x3FF) << 0))#define hwirq_to_sid (hwirq) (((hwirq) >> 28) & 0xF)#define hwirq_to_per (hwirq) (((hwirq) >> 20) & 0xFF)#define hwirq_to_irq (hwirq) (((hwirq) >> 16) & 0x7) -#define hwirq_to_apid (hwirq) (((hwirq) >> 0) & 0x1FF) +#define hwirq_to_apid (hwirq) (((hwirq) >> 0) & 0x3FF)struct pmic_arb_ver_ops ;
@@ -130,13 +136,21 @@ struct apid_data {* @channel: execution environment channel to use for accesses. * @irq: PMIC ARB interrupt. * @ee: the current Execution Environment +* @bus_instance: on v7: 0 = primary SPMI bus, 1 = secondary SPMI bus * @min_apid: minimum APID (used for bounding IRQ search) * @max_apid: maximum APID +* @base_apid: on v7: minimum APID associated with the particular SPMI +* bus instance +* @apid_count: on v5 and v7: number of APIDs associated with the +* particular SPMI bus instance * @mapping_table: in-memory copy of PPID -> APID mapping table. * @domain: irq domain object for PMIC IRQ domain * @spmic: SPMI controller object * @ver_ops: version dependent operations. -* @ppid_to_apid in-memory copy of PPID -> APID mapping table. +* @ppid_to_apid: in-memory copy of PPID -> APID mapping table. +* @last_apid: Highest value APID in use +* @apid_data: Table of data for all APIDs +* @max_periphs: Number of elements in apid_data[] */ struct spmi_pmic_arb {void __iomem *rd_base;
@@ -149,8 +163,11 @@ struct spmi_pmic_arb {u8 channel;int irq;u8 ee; +u32 bus_instance;u16 min_apid;u16 max_apid; +u16 base_apid; +int apid_count;u32 *mapping_table;DECLARE_BITMAP (mapping_table_valid,PMIC_ARB_MAX_PERIPHS );struct irq_domain *domain;
@@ -158,7 +175,8 @@ struct spmi_pmic_arb {const struct pmic_arb_ver_ops *ver_ops;u16 *ppid_to_apid;u16 last_apid; -struct apid_data apid_data[PMIC_ARB_MAX_PERIPHS ]; +struct apid_data *apid_data; +int max_periphs; };/**
@@ -180,6 +198,7 @@ struct spmi_pmic_arb {* @irq_clear: on v1 address of PMIC_ARB_SPMI_PIC_IRQ_CLEARn * on v2 address of SPMI_PIC_IRQ_CLEARn. * @apid_map_offset: offset of PMIC_ARB_REG_CHNLn +* @apid_owner: on v2 and later address of SPMI_PERIPHn_2OWNER_TABLE_REG */ struct pmic_arb_ver_ops {const char *ver_str;
@@ -196,6 +215,7 @@ struct pmic_arb_ver_ops {void __iomem *(*irq_status)(struct spmi_pmic_arb *pmic_arb,u16 n);void __iomem *(*irq_clear)(struct spmi_pmic_arb *pmic_arb,u16 n);u32 (*apid_map_offset)(u16 n); +void __iomem *(*apid_owner)(struct spmi_pmic_arb *pmic_arb,u16 n); }; static inline void pmic_arb_base_write(struct spmi_pmic_arb *pmic_arb,
@@ -627,6 +647,11 @@ static void pmic_arb_chained_irq(struct irq_desc *desc)struct irq_chip *chip =irq_desc_get_chip (desc);int first = pmic_arb->min_apid;int last = pmic_arb->max_apid; +/* +* acc_offset will be non-zero for the secondary SPMI bus instance on +* v7 controllers. +*/ +int acc_offset = pmic_arb->base_apid >>5 ;u8 ee = pmic_arb->ee;u32 status, enable, handled =0 ;int i, id, apid;
@@ -637,8 +662,7 @@ static void pmic_arb_chained_irq(struct irq_desc *desc)chained_irq_enter (chip, desc);for (i = first >>5 ; i <= last >>5 ; ++i) { - status =readl_relaxed ( - ver_ops->owner_acc_status (pmic_arb, ee, i)); + status =readl_relaxed (ver_ops->owner_acc_status (pmic_arb, ee, i - acc_offset));if (status) acc_valid = true;
@@ -983,8 +1007,8 @@ static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pmic_arb, u16 ppid)if (offset >= pmic_arb->core_size)break ; - regval =readl_relaxed (pmic_arb->cnfg + -SPMI_OWNERSHIP_TABLE_REG (apid)); + regval =readl_relaxed (pmic_arb->ver_ops->apid_owner (pmic_arb, + apid)); apidd->irq_ee =SPMI_OWNERSHIP_PERIPH2OWNER (regval); apidd->write_ee = apidd->irq_ee;
@@ -1020,21 +1044,30 @@ static int pmic_arb_ppid_to_apid_v2(struct spmi_pmic_arb *pmic_arb, u16 ppid)static int pmic_arb_read_apid_map_v5 (struct spmi_pmic_arb *pmic_arb) { -struct apid_data *apidd = pmic_arb->apid_data; +struct apid_data *apidd;struct apid_data *prev_apidd; -u16 i, apid, ppid; +u16 i, apid, ppid, apid_max;bool valid, is_irq_ee;u32 regval, offset;/* * In order to allow multiple EEs to write to a single PPID in arbiter -* version 5, there is more than one APID mapped to each PPID. +* version 5 and 7, there is more than one APID mapped to each PPID. * The owner field for each of these mappings specifies the EE which is * allowed to write to the APID. The owner of the last (highest) APID * which has the IRQ owner bit set for a given PPID will receive * interrupts from the PPID. +* +* In arbiter version 7, the APID numbering space is divided between +* the primary bus (0) and secondary bus (1) such that: +* APID = 0 to N-1 are assigned to the primary bus +* APID = N to N+M-1 are assigned to the secondary bus +* where N = number of APIDs supported by the primary bus and +* M = number of APIDs supported by the secondary bus */ -for (i =0 ; ; i++, apidd++) { + apidd = &pmic_arb->apid_data[pmic_arb->base_apid]; + apid_max = pmic_arb->base_apid + pmic_arb->apid_count; +for (i = pmic_arb->base_apid; i < apid_max; i++, apidd++) { offset = pmic_arb->ver_ops->apid_map_offset (i);if (offset >= pmic_arb->core_size)break ;
@@ -1045,8 +1078,8 @@ static int pmic_arb_read_apid_map_v5(struct spmi_pmic_arb *pmic_arb) ppid = (regval >>8 ) &PMIC_ARB_PPID_MASK ; is_irq_ee =PMIC_ARB_CHAN_IS_IRQ_OWNER (regval); - regval =readl_relaxed (pmic_arb->cnfg + -SPMI_OWNERSHIP_TABLE_REG (i)); + regval =readl_relaxed (pmic_arb->ver_ops->apid_owner (pmic_arb, + i)); apidd->write_ee =SPMI_OWNERSHIP_PERIPH2OWNER (regval); apidd->irq_ee = is_irq_ee ? apidd->write_ee :INVALID_EE ;
@@ -1145,6 +1178,40 @@ static int pmic_arb_offset_v5(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr,return offset; } +/* +* v7 offset per ee and per apid for observer channels and per apid for +* read/write channels. +*/ +static int pmic_arb_offset_v7 (struct spmi_pmic_arb *pmic_arb,u8 sid,u16 addr, +enum pmic_arb_channel ch_type) +{ +u16 apid; +int rc; +u32 offset =0 ; +u16 ppid = (sid <<8 ) | (addr >>8 ); + + rc = pmic_arb->ver_ops->ppid_to_apid (pmic_arb, ppid); +if (rc <0 ) +return rc; + + apid = rc; +switch (ch_type) { +case PMIC_ARB_CHANNEL_OBS : + offset =0x8000 * pmic_arb->ee +0x20 * apid; +break ; +case PMIC_ARB_CHANNEL_RW : +if (pmic_arb->apid_data[apid].write_ee != pmic_arb->ee) { +dev_err (&pmic_arb->spmic->dev,"disallowed SPMI write to sid=%u, addr=0x%04X\n" , + sid, addr); +return -EPERM ; + } + offset =0x1000 * apid; +break ; + } + +return offset; +} +static u32 pmic_arb_fmt_cmd_v1 (u8 opc,u8 sid,u16 addr,u8 bc) {return (opc <<27 ) | ((sid &0xf ) <<20 ) | (addr <<4 ) | (bc &0x7 );
@@ -1179,6 +1246,12 @@ pmic_arb_owner_acc_status_v5(struct spmi_pmic_arb *pmic_arb, u8 m, u16 n)return pmic_arb->intr +0x10000 * m +0x4 * n; } +static void __iomem * +pmic_arb_owner_acc_status_v7 (struct spmi_pmic_arb *pmic_arb,u8 m,u16 n) +{ +return pmic_arb->intr +0x1000 * m +0x4 * n; +} +static void __iomem *pmic_arb_acc_enable_v1 (struct spmi_pmic_arb *pmic_arb,u16 n) {
@@ -1197,6 +1270,12 @@ pmic_arb_acc_enable_v5(struct spmi_pmic_arb *pmic_arb, u16 n)return pmic_arb->wr_base +0x100 +0x10000 * n; } +static void __iomem * +pmic_arb_acc_enable_v7 (struct spmi_pmic_arb *pmic_arb,u16 n) +{ +return pmic_arb->wr_base +0x100 +0x1000 * n; +} +static void __iomem *pmic_arb_irq_status_v1 (struct spmi_pmic_arb *pmic_arb,u16 n) {
@@ -1215,6 +1294,12 @@ pmic_arb_irq_status_v5(struct spmi_pmic_arb *pmic_arb, u16 n)return pmic_arb->wr_base +0x104 +0x10000 * n; } +static void __iomem * +pmic_arb_irq_status_v7 (struct spmi_pmic_arb *pmic_arb,u16 n) +{ +return pmic_arb->wr_base +0x104 +0x1000 * n; +} +static void __iomem *pmic_arb_irq_clear_v1 (struct spmi_pmic_arb *pmic_arb,u16 n) {
@@ -1233,6 +1318,12 @@ pmic_arb_irq_clear_v5(struct spmi_pmic_arb *pmic_arb, u16 n)return pmic_arb->wr_base +0x108 +0x10000 * n; } +static void __iomem * +pmic_arb_irq_clear_v7 (struct spmi_pmic_arb *pmic_arb,u16 n) +{ +return pmic_arb->wr_base +0x108 +0x1000 * n; +} +static u32 pmic_arb_apid_map_offset_v2 (u16 n) {return 0x800 +0x4 * n;
@@ -1243,6 +1334,28 @@ static u32 pmic_arb_apid_map_offset_v5(u16 n)return 0x900 +0x4 * n; } +static u32 pmic_arb_apid_map_offset_v7 (u16 n) +{ +return 0x2000 +0x4 * n; +} + +static void __iomem * +pmic_arb_apid_owner_v2 (struct spmi_pmic_arb *pmic_arb,u16 n) +{ +return pmic_arb->cnfg +0x700 +0x4 * n; +} + +/* +* For arbiter version 7, APID ownership table registers have independent +* numbering space for each SPMI bus instance, so each is indexed starting from +* 0. +*/ +static void __iomem * +pmic_arb_apid_owner_v7 (struct spmi_pmic_arb *pmic_arb,u16 n) +{ +return pmic_arb->cnfg +0x4 * (n - pmic_arb->base_apid); +} +static const struct pmic_arb_ver_ops pmic_arb_v1 = { .ver_str ="v1" , .ppid_to_apid = pmic_arb_ppid_to_apid_v1,
@@ -1254,6 +1367,7 @@ static const struct pmic_arb_ver_ops pmic_arb_v1 = { .irq_status = pmic_arb_irq_status_v1, .irq_clear = pmic_arb_irq_clear_v1, .apid_map_offset = pmic_arb_apid_map_offset_v2, + .apid_owner = pmic_arb_apid_owner_v2, };static const struct pmic_arb_ver_ops pmic_arb_v2 = {
@@ -1267,6 +1381,7 @@ static const struct pmic_arb_ver_ops pmic_arb_v2 = { .irq_status = pmic_arb_irq_status_v2, .irq_clear = pmic_arb_irq_clear_v2, .apid_map_offset = pmic_arb_apid_map_offset_v2, + .apid_owner = pmic_arb_apid_owner_v2, };static const struct pmic_arb_ver_ops pmic_arb_v3 = {
@@ -1280,6 +1395,7 @@ static const struct pmic_arb_ver_ops pmic_arb_v3 = { .irq_status = pmic_arb_irq_status_v2, .irq_clear = pmic_arb_irq_clear_v2, .apid_map_offset = pmic_arb_apid_map_offset_v2, + .apid_owner = pmic_arb_apid_owner_v2, };static const struct pmic_arb_ver_ops pmic_arb_v5 = {
@@ -1293,6 +1409,21 @@ static const struct pmic_arb_ver_ops pmic_arb_v5 = { .irq_status = pmic_arb_irq_status_v5, .irq_clear = pmic_arb_irq_clear_v5, .apid_map_offset = pmic_arb_apid_map_offset_v5, + .apid_owner = pmic_arb_apid_owner_v2, +}; + +static const struct pmic_arb_ver_ops pmic_arb_v7 = { + .ver_str ="v7" , + .ppid_to_apid = pmic_arb_ppid_to_apid_v5, + .non_data_cmd = pmic_arb_non_data_cmd_v2, + .offset = pmic_arb_offset_v7, + .fmt_cmd = pmic_arb_fmt_cmd_v2, + .owner_acc_status = pmic_arb_owner_acc_status_v7, + .acc_enable = pmic_arb_acc_enable_v7, + .irq_status = pmic_arb_irq_status_v7, + .irq_clear = pmic_arb_irq_clear_v7, + .apid_map_offset = pmic_arb_apid_map_offset_v7, + .apid_owner = pmic_arb_apid_owner_v7, };static const struct irq_domain_ops pmic_arb_irq_domain_ops = {
@@ -1319,8 +1450,18 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev) pmic_arb =spmi_controller_get_drvdata (ctrl); pmic_arb->spmic = ctrl; +/* +* Please don't replace this with devm_platform_ioremap_resource() or +* devm_ioremap_resource(). These both result in a call to +* devm_request_mem_region() which prevents multiple mappings of this +* register address range. SoCs with PMIC arbiter v7 may define two +* arbiter devices, for the two physical SPMI interfaces, which share +* some register address ranges (i.e. "core", "obsrvr", and "chnls"). +* Ensure that both devices probe successfully by calling devm_ioremap() +* which does not result in a devm_request_mem_region() call. +*/ res =platform_get_resource_byname (pdev,IORESOURCE_MEM ,"core" ); - core =devm_ioremap_resource (&ctrl->dev, res); + core =devm_ioremap (&ctrl->dev, res->start,resource_size (res));if (IS_ERR (core)) { err =PTR_ERR (core); goto err_put_ctrl;
@@ -1349,12 +1490,15 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev) pmic_arb->ver_ops = &pmic_arb_v2; else if (hw_ver < PMIC_ARB_VERSION_V5_MIN) pmic_arb->ver_ops = &pmic_arb_v3; - else + else if (hw_ver < PMIC_ARB_VERSION_V7_MIN) pmic_arb->ver_ops = &pmic_arb_v5; + else + pmic_arb->ver_ops = &pmic_arb_v7; res =platform_get_resource_byname (pdev,IORESOURCE_MEM ,"obsrvr" ); - pmic_arb->rd_base =devm_ioremap_resource (&ctrl->dev, res); + pmic_arb->rd_base =devm_ioremap (&ctrl->dev, res->start, +resource_size (res));if (IS_ERR (pmic_arb->rd_base)) { err =PTR_ERR (pmic_arb->rd_base); goto err_put_ctrl;
@@ -1362,13 +1506,69 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev) res =platform_get_resource_byname (pdev,IORESOURCE_MEM ,"chnls" ); - pmic_arb->wr_base =devm_ioremap_resource (&ctrl->dev, res); + pmic_arb->wr_base =devm_ioremap (&ctrl->dev, res->start, +resource_size (res));if (IS_ERR (pmic_arb->wr_base)) { err =PTR_ERR (pmic_arb->wr_base); goto err_put_ctrl; } } + pmic_arb->max_periphs =PMIC_ARB_MAX_PERIPHS ; + +if (hw_ver >=PMIC_ARB_VERSION_V7_MIN ) { + pmic_arb->max_periphs =PMIC_ARB_MAX_PERIPHS_V7 ; +/* Optional property for v7: */ +of_property_read_u32 (pdev->dev.of_node,"qcom,bus-id" , + &pmic_arb->bus_instance); +if (pmic_arb->bus_instance >1 ) { + err = -EINVAL ; +dev_err (&pdev->dev,"invalid bus instance (%u) specified\n" , + pmic_arb->bus_instance); + goto err_put_ctrl; + } + +if (pmic_arb->bus_instance ==0 ) { + pmic_arb->base_apid =0 ; + pmic_arb->apid_count = +readl_relaxed (core +PMIC_ARB_FEATURES ) & +PMIC_ARB_FEATURES_PERIPH_MASK ; + }else { + pmic_arb->base_apid = +readl_relaxed (core +PMIC_ARB_FEATURES ) & +PMIC_ARB_FEATURES_PERIPH_MASK ; + pmic_arb->apid_count = +readl_relaxed (core +PMIC_ARB_FEATURES1 ) & +PMIC_ARB_FEATURES_PERIPH_MASK ; + } + +if (pmic_arb->base_apid + pmic_arb->apid_count > pmic_arb->max_periphs) { + err = -EINVAL ; +dev_err (&pdev->dev,"Unsupported APID count %d detected\n" , + pmic_arb->base_apid + pmic_arb->apid_count); + goto err_put_ctrl; + } + }else if (hw_ver >=PMIC_ARB_VERSION_V5_MIN ) { + pmic_arb->base_apid =0 ; + pmic_arb->apid_count =readl_relaxed (core +PMIC_ARB_FEATURES ) & +PMIC_ARB_FEATURES_PERIPH_MASK ; + +if (pmic_arb->apid_count > pmic_arb->max_periphs) { + err = -EINVAL ; +dev_err (&pdev->dev,"Unsupported APID count %d detected\n" , + pmic_arb->apid_count); + goto err_put_ctrl; + } + } + + pmic_arb->apid_data =devm_kcalloc (&ctrl->dev, pmic_arb->max_periphs, +sizeof (*pmic_arb->apid_data), +GFP_KERNEL ); +if (!pmic_arb->apid_data) { + err = -ENOMEM ; + goto err_put_ctrl; + } +dev_info (&ctrl->dev,"PMIC arbiter version %s (0x%x)\n" , pmic_arb->ver_ops->ver_str, hw_ver);
@@ -1420,7 +1620,7 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev) } pmic_arb->ee = ee; - mapping_table =devm_kcalloc (&ctrl->dev,PMIC_ARB_MAX_PERIPHS , + mapping_table =devm_kcalloc (&ctrl->dev, pmic_arb->max_periphs,sizeof (*mapping_table),GFP_KERNEL );if (!mapping_table) { err = -ENOMEM ;
@@ -1431,7 +1631,7 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)/* Initialize max_apid/min_apid to the opposite bounds, during * the irq domain translation, we are sure to update these */ pmic_arb->max_apid =0 ; - pmic_arb->min_apid =PMIC_ARB_MAX_PERIPHS -1 ; + pmic_arb->min_apid = pmic_arb->max_periphs -1 ;platform_set_drvdata (pdev, ctrl);raw_spin_lock_init (&pmic_arb->lock);
Signature · 1 line
2.37.3
Quoted 8 lines · Vinod Koul
From: David Collins <[email protected]>
PMIC v7 has different offset values and seqeunces, so add support for this new version of PMIC
Signed-off-by David Collins <[email protected]>Signed-off-by Vinod Koul <[email protected]>
Regards,
Bjorn
Quoted 492 lines
--- drivers/spmi/spmi-pmic-arb.c | 242 ++++++++++++++++++++++++++++++++--- 1 file changed, 221 insertions(+), 21 deletions(-)drivers/spmi/spmi-pmic-arb.c +221
-21@@ -22,8 +22,14 @@#define PMIC_ARB_VERSION_V2_MIN 0x20010000#define PMIC_ARB_VERSION_V3_MIN 0x30000000#define PMIC_ARB_VERSION_V5_MIN 0x50000000 +#define PMIC_ARB_VERSION_V7_MIN 0x70000000#define PMIC_ARB_INT_EN 0x0004 +#define PMIC_ARB_FEATURES 0x0004 +#define PMIC_ARB_FEATURES_PERIPH_MASK GENMASK(10, 0) + +#define PMIC_ARB_FEATURES1 0x0008 +/* PMIC Arbiter channel registers offsets */ #define PMIC_ARB_CMD 0x00#define PMIC_ARB_CONFIG 0x04@@ -48,7 +54,6 @@#define INVALID_EE 0xFF/* Ownership Table */ -#define SPMI_OWNERSHIP_TABLE_REG (N ) (0x0700 + (4 * (N)))#define SPMI_OWNERSHIP_PERIPH2OWNER (X ) ((X) & 0x7)/* Channel Status fields */ @@ -91,6 +96,7 @@ enum pmic_arb_channel {/* Maximum number of support PMIC peripherals */ #define PMIC_ARB_MAX_PERIPHS 512 +#define PMIC_ARB_MAX_PERIPHS_V7 1024#define PMIC_ARB_TIMEOUT_US 1000#define PMIC_ARB_MAX_TRANS_BYTES (8)@@ -104,12 +110,12 @@ enum pmic_arb_channel { ((((slave_id) &0xF ) <<28 ) | \ (((periph_id) &0xFF ) <<20 ) | \ (((irq_id) &0x7 ) <<16 ) | \ - (((apid) & 0x1FF) << 0)) + (((apid) & 0x3FF) << 0))#define hwirq_to_sid (hwirq) (((hwirq) >> 28) & 0xF)#define hwirq_to_per (hwirq) (((hwirq) >> 20) & 0xFF)#define hwirq_to_irq (hwirq) (((hwirq) >> 16) & 0x7) -#define hwirq_to_apid (hwirq) (((hwirq) >> 0) & 0x1FF) +#define hwirq_to_apid (hwirq) (((hwirq) >> 0) & 0x3FF)struct pmic_arb_ver_ops ;@@ -130,13 +136,21 @@ struct apid_data {* @channel: execution environment channel to use for accesses. * @irq: PMIC ARB interrupt. * @ee: the current Execution Environment +* @bus_instance: on v7: 0 = primary SPMI bus, 1 = secondary SPMI bus * @min_apid: minimum APID (used for bounding IRQ search) * @max_apid: maximum APID +* @base_apid: on v7: minimum APID associated with the particular SPMI +* bus instance +* @apid_count: on v5 and v7: number of APIDs associated with the +* particular SPMI bus instance * @mapping_table: in-memory copy of PPID -> APID mapping table. * @domain: irq domain object for PMIC IRQ domain * @spmic: SPMI controller object * @ver_ops: version dependent operations. -* @ppid_to_apid in-memory copy of PPID -> APID mapping table. +* @ppid_to_apid: in-memory copy of PPID -> APID mapping table. +* @last_apid: Highest value APID in use +* @apid_data: Table of data for all APIDs +* @max_periphs: Number of elements in apid_data[] */ struct spmi_pmic_arb {void __iomem *rd_base;@@ -149,8 +163,11 @@ struct spmi_pmic_arb {u8 channel;int irq;u8 ee; +u32 bus_instance;u16 min_apid;u16 max_apid; +u16 base_apid; +int apid_count;u32 *mapping_table;DECLARE_BITMAP (mapping_table_valid,PMIC_ARB_MAX_PERIPHS );struct irq_domain *domain;@@ -158,7 +175,8 @@ struct spmi_pmic_arb {const struct pmic_arb_ver_ops *ver_ops;u16 *ppid_to_apid;u16 last_apid; -struct apid_data apid_data[PMIC_ARB_MAX_PERIPHS ]; +struct apid_data *apid_data; +int max_periphs; };/** @@ -180,6 +198,7 @@ struct spmi_pmic_arb {* @irq_clear: on v1 address of PMIC_ARB_SPMI_PIC_IRQ_CLEARn * on v2 address of SPMI_PIC_IRQ_CLEARn. * @apid_map_offset: offset of PMIC_ARB_REG_CHNLn +* @apid_owner: on v2 and later address of SPMI_PERIPHn_2OWNER_TABLE_REG */ struct pmic_arb_ver_ops {const char *ver_str;@@ -196,6 +215,7 @@ struct pmic_arb_ver_ops {void __iomem *(*irq_status)(struct spmi_pmic_arb *pmic_arb,u16 n);void __iomem *(*irq_clear)(struct spmi_pmic_arb *pmic_arb,u16 n);u32 (*apid_map_offset)(u16 n); +void __iomem *(*apid_owner)(struct spmi_pmic_arb *pmic_arb,u16 n); }; static inline void pmic_arb_base_write(struct spmi_pmic_arb *pmic_arb,@@ -627,6 +647,11 @@ static void pmic_arb_chained_irq(struct irq_desc *desc)struct irq_chip *chip =irq_desc_get_chip (desc);int first = pmic_arb->min_apid;int last = pmic_arb->max_apid; +/* +* acc_offset will be non-zero for the secondary SPMI bus instance on +* v7 controllers. +*/ +int acc_offset = pmic_arb->base_apid >>5 ;u8 ee = pmic_arb->ee;u32 status, enable, handled =0 ;int i, id, apid;@@ -637,8 +662,7 @@ static void pmic_arb_chained_irq(struct irq_desc *desc)chained_irq_enter (chip, desc);for (i = first >>5 ; i <= last >>5 ; ++i) { - status =readl_relaxed ( - ver_ops->owner_acc_status (pmic_arb, ee, i)); + status =readl_relaxed (ver_ops->owner_acc_status (pmic_arb, ee, i - acc_offset));if (status) acc_valid = true;@@ -983,8 +1007,8 @@ static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pmic_arb, u16 ppid)if (offset >= pmic_arb->core_size)break ; - regval =readl_relaxed (pmic_arb->cnfg + -SPMI_OWNERSHIP_TABLE_REG (apid)); + regval =readl_relaxed (pmic_arb->ver_ops->apid_owner (pmic_arb, + apid)); apidd->irq_ee =SPMI_OWNERSHIP_PERIPH2OWNER (regval); apidd->write_ee = apidd->irq_ee;@@ -1020,21 +1044,30 @@ static int pmic_arb_ppid_to_apid_v2(struct spmi_pmic_arb *pmic_arb, u16 ppid)static int pmic_arb_read_apid_map_v5 (struct spmi_pmic_arb *pmic_arb) { -struct apid_data *apidd = pmic_arb->apid_data; +struct apid_data *apidd;struct apid_data *prev_apidd; -u16 i, apid, ppid; +u16 i, apid, ppid, apid_max;bool valid, is_irq_ee;u32 regval, offset;/* * In order to allow multiple EEs to write to a single PPID in arbiter -* version 5, there is more than one APID mapped to each PPID. +* version 5 and 7, there is more than one APID mapped to each PPID. * The owner field for each of these mappings specifies the EE which is * allowed to write to the APID. The owner of the last (highest) APID * which has the IRQ owner bit set for a given PPID will receive * interrupts from the PPID. +* +* In arbiter version 7, the APID numbering space is divided between +* the primary bus (0) and secondary bus (1) such that: +* APID = 0 to N-1 are assigned to the primary bus +* APID = N to N+M-1 are assigned to the secondary bus +* where N = number of APIDs supported by the primary bus and +* M = number of APIDs supported by the secondary bus */ -for (i =0 ; ; i++, apidd++) { + apidd = &pmic_arb->apid_data[pmic_arb->base_apid]; + apid_max = pmic_arb->base_apid + pmic_arb->apid_count; +for (i = pmic_arb->base_apid; i < apid_max; i++, apidd++) { offset = pmic_arb->ver_ops->apid_map_offset (i);if (offset >= pmic_arb->core_size)break ;@@ -1045,8 +1078,8 @@ static int pmic_arb_read_apid_map_v5(struct spmi_pmic_arb *pmic_arb) ppid = (regval >>8 ) &PMIC_ARB_PPID_MASK ; is_irq_ee =PMIC_ARB_CHAN_IS_IRQ_OWNER (regval); - regval =readl_relaxed (pmic_arb->cnfg + -SPMI_OWNERSHIP_TABLE_REG (i)); + regval =readl_relaxed (pmic_arb->ver_ops->apid_owner (pmic_arb, + i)); apidd->write_ee =SPMI_OWNERSHIP_PERIPH2OWNER (regval); apidd->irq_ee = is_irq_ee ? apidd->write_ee :INVALID_EE ;@@ -1145,6 +1178,40 @@ static int pmic_arb_offset_v5(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr,return offset; } +/* +* v7 offset per ee and per apid for observer channels and per apid for +* read/write channels. +*/ +static int pmic_arb_offset_v7 (struct spmi_pmic_arb *pmic_arb,u8 sid,u16 addr, +enum pmic_arb_channel ch_type) +{ +u16 apid; +int rc; +u32 offset =0 ; +u16 ppid = (sid <<8 ) | (addr >>8 ); + + rc = pmic_arb->ver_ops->ppid_to_apid (pmic_arb, ppid); +if (rc <0 ) +return rc; + + apid = rc; +switch (ch_type) { +case PMIC_ARB_CHANNEL_OBS : + offset =0x8000 * pmic_arb->ee +0x20 * apid; +break ; +case PMIC_ARB_CHANNEL_RW : +if (pmic_arb->apid_data[apid].write_ee != pmic_arb->ee) { +dev_err (&pmic_arb->spmic->dev,"disallowed SPMI write to sid=%u, addr=0x%04X\n" , + sid, addr); +return -EPERM ; + } + offset =0x1000 * apid; +break ; + } + +return offset; +} +static u32 pmic_arb_fmt_cmd_v1 (u8 opc,u8 sid,u16 addr,u8 bc) {return (opc <<27 ) | ((sid &0xf ) <<20 ) | (addr <<4 ) | (bc &0x7 );@@ -1179,6 +1246,12 @@ pmic_arb_owner_acc_status_v5(struct spmi_pmic_arb *pmic_arb, u8 m, u16 n)return pmic_arb->intr +0x10000 * m +0x4 * n; } +static void __iomem * +pmic_arb_owner_acc_status_v7 (struct spmi_pmic_arb *pmic_arb,u8 m,u16 n) +{ +return pmic_arb->intr +0x1000 * m +0x4 * n; +} +static void __iomem *pmic_arb_acc_enable_v1 (struct spmi_pmic_arb *pmic_arb,u16 n) {@@ -1197,6 +1270,12 @@ pmic_arb_acc_enable_v5(struct spmi_pmic_arb *pmic_arb, u16 n)return pmic_arb->wr_base +0x100 +0x10000 * n; } +static void __iomem * +pmic_arb_acc_enable_v7 (struct spmi_pmic_arb *pmic_arb,u16 n) +{ +return pmic_arb->wr_base +0x100 +0x1000 * n; +} +static void __iomem *pmic_arb_irq_status_v1 (struct spmi_pmic_arb *pmic_arb,u16 n) {@@ -1215,6 +1294,12 @@ pmic_arb_irq_status_v5(struct spmi_pmic_arb *pmic_arb, u16 n)return pmic_arb->wr_base +0x104 +0x10000 * n; } +static void __iomem * +pmic_arb_irq_status_v7 (struct spmi_pmic_arb *pmic_arb,u16 n) +{ +return pmic_arb->wr_base +0x104 +0x1000 * n; +} +static void __iomem *pmic_arb_irq_clear_v1 (struct spmi_pmic_arb *pmic_arb,u16 n) {@@ -1233,6 +1318,12 @@ pmic_arb_irq_clear_v5(struct spmi_pmic_arb *pmic_arb, u16 n)return pmic_arb->wr_base +0x108 +0x10000 * n; } +static void __iomem * +pmic_arb_irq_clear_v7 (struct spmi_pmic_arb *pmic_arb,u16 n) +{ +return pmic_arb->wr_base +0x108 +0x1000 * n; +} +static u32 pmic_arb_apid_map_offset_v2 (u16 n) {return 0x800 +0x4 * n;@@ -1243,6 +1334,28 @@ static u32 pmic_arb_apid_map_offset_v5(u16 n)return 0x900 +0x4 * n; } +static u32 pmic_arb_apid_map_offset_v7 (u16 n) +{ +return 0x2000 +0x4 * n; +} + +static void __iomem * +pmic_arb_apid_owner_v2 (struct spmi_pmic_arb *pmic_arb,u16 n) +{ +return pmic_arb->cnfg +0x700 +0x4 * n; +} + +/* +* For arbiter version 7, APID ownership table registers have independent +* numbering space for each SPMI bus instance, so each is indexed starting from +* 0. +*/ +static void __iomem * +pmic_arb_apid_owner_v7 (struct spmi_pmic_arb *pmic_arb,u16 n) +{ +return pmic_arb->cnfg +0x4 * (n - pmic_arb->base_apid); +} +static const struct pmic_arb_ver_ops pmic_arb_v1 = { .ver_str ="v1" , .ppid_to_apid = pmic_arb_ppid_to_apid_v1,@@ -1254,6 +1367,7 @@ static const struct pmic_arb_ver_ops pmic_arb_v1 = { .irq_status = pmic_arb_irq_status_v1, .irq_clear = pmic_arb_irq_clear_v1, .apid_map_offset = pmic_arb_apid_map_offset_v2, + .apid_owner = pmic_arb_apid_owner_v2, };static const struct pmic_arb_ver_ops pmic_arb_v2 = {@@ -1267,6 +1381,7 @@ static const struct pmic_arb_ver_ops pmic_arb_v2 = { .irq_status = pmic_arb_irq_status_v2, .irq_clear = pmic_arb_irq_clear_v2, .apid_map_offset = pmic_arb_apid_map_offset_v2, + .apid_owner = pmic_arb_apid_owner_v2, };static const struct pmic_arb_ver_ops pmic_arb_v3 = {@@ -1280,6 +1395,7 @@ static const struct pmic_arb_ver_ops pmic_arb_v3 = { .irq_status = pmic_arb_irq_status_v2, .irq_clear = pmic_arb_irq_clear_v2, .apid_map_offset = pmic_arb_apid_map_offset_v2, + .apid_owner = pmic_arb_apid_owner_v2, };static const struct pmic_arb_ver_ops pmic_arb_v5 = {@@ -1293,6 +1409,21 @@ static const struct pmic_arb_ver_ops pmic_arb_v5 = { .irq_status = pmic_arb_irq_status_v5, .irq_clear = pmic_arb_irq_clear_v5, .apid_map_offset = pmic_arb_apid_map_offset_v5, + .apid_owner = pmic_arb_apid_owner_v2, +}; + +static const struct pmic_arb_ver_ops pmic_arb_v7 = { + .ver_str ="v7" , + .ppid_to_apid = pmic_arb_ppid_to_apid_v5, + .non_data_cmd = pmic_arb_non_data_cmd_v2, + .offset = pmic_arb_offset_v7, + .fmt_cmd = pmic_arb_fmt_cmd_v2, + .owner_acc_status = pmic_arb_owner_acc_status_v7, + .acc_enable = pmic_arb_acc_enable_v7, + .irq_status = pmic_arb_irq_status_v7, + .irq_clear = pmic_arb_irq_clear_v7, + .apid_map_offset = pmic_arb_apid_map_offset_v7, + .apid_owner = pmic_arb_apid_owner_v7, };static const struct irq_domain_ops pmic_arb_irq_domain_ops = {@@ -1319,8 +1450,18 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev) pmic_arb =spmi_controller_get_drvdata (ctrl); pmic_arb->spmic = ctrl; +/* +* Please don't replace this with devm_platform_ioremap_resource() or +* devm_ioremap_resource(). These both result in a call to +* devm_request_mem_region() which prevents multiple mappings of this +* register address range. SoCs with PMIC arbiter v7 may define two +* arbiter devices, for the two physical SPMI interfaces, which share +* some register address ranges (i.e. "core", "obsrvr", and "chnls"). +* Ensure that both devices probe successfully by calling devm_ioremap() +* which does not result in a devm_request_mem_region() call. +*/ res =platform_get_resource_byname (pdev,IORESOURCE_MEM ,"core" ); - core =devm_ioremap_resource (&ctrl->dev, res); + core =devm_ioremap (&ctrl->dev, res->start,resource_size (res));if (IS_ERR (core)) { err =PTR_ERR (core); goto err_put_ctrl;@@ -1349,12 +1490,15 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev) pmic_arb->ver_ops = &pmic_arb_v2; else if (hw_ver < PMIC_ARB_VERSION_V5_MIN) pmic_arb->ver_ops = &pmic_arb_v3; - else + else if (hw_ver < PMIC_ARB_VERSION_V7_MIN) pmic_arb->ver_ops = &pmic_arb_v5; + else + pmic_arb->ver_ops = &pmic_arb_v7; res =platform_get_resource_byname (pdev,IORESOURCE_MEM ,"obsrvr" ); - pmic_arb->rd_base =devm_ioremap_resource (&ctrl->dev, res); + pmic_arb->rd_base =devm_ioremap (&ctrl->dev, res->start, +resource_size (res));if (IS_ERR (pmic_arb->rd_base)) { err =PTR_ERR (pmic_arb->rd_base); goto err_put_ctrl;@@ -1362,13 +1506,69 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev) res =platform_get_resource_byname (pdev,IORESOURCE_MEM ,"chnls" ); - pmic_arb->wr_base =devm_ioremap_resource (&ctrl->dev, res); + pmic_arb->wr_base =devm_ioremap (&ctrl->dev, res->start, +resource_size (res));if (IS_ERR (pmic_arb->wr_base)) { err =PTR_ERR (pmic_arb->wr_base); goto err_put_ctrl; } } + pmic_arb->max_periphs =PMIC_ARB_MAX_PERIPHS ; + +if (hw_ver >=PMIC_ARB_VERSION_V7_MIN ) { + pmic_arb->max_periphs =PMIC_ARB_MAX_PERIPHS_V7 ; +/* Optional property for v7: */ +of_property_read_u32 (pdev->dev.of_node,"qcom,bus-id" , + &pmic_arb->bus_instance); +if (pmic_arb->bus_instance >1 ) { + err = -EINVAL ; +dev_err (&pdev->dev,"invalid bus instance (%u) specified\n" , + pmic_arb->bus_instance); + goto err_put_ctrl; + } + +if (pmic_arb->bus_instance ==0 ) { + pmic_arb->base_apid =0 ; + pmic_arb->apid_count = +readl_relaxed (core +PMIC_ARB_FEATURES ) & +PMIC_ARB_FEATURES_PERIPH_MASK ; + }else { + pmic_arb->base_apid = +readl_relaxed (core +PMIC_ARB_FEATURES ) & +PMIC_ARB_FEATURES_PERIPH_MASK ; + pmic_arb->apid_count = +readl_relaxed (core +PMIC_ARB_FEATURES1 ) & +PMIC_ARB_FEATURES_PERIPH_MASK ; + } + +if (pmic_arb->base_apid + pmic_arb->apid_count > pmic_arb->max_periphs) { + err = -EINVAL ; +dev_err (&pdev->dev,"Unsupported APID count %d detected\n" , + pmic_arb->base_apid + pmic_arb->apid_count); + goto err_put_ctrl; + } + }else if (hw_ver >=PMIC_ARB_VERSION_V5_MIN ) { + pmic_arb->base_apid =0 ; + pmic_arb->apid_count =readl_relaxed (core +PMIC_ARB_FEATURES ) & +PMIC_ARB_FEATURES_PERIPH_MASK ; + +if (pmic_arb->apid_count > pmic_arb->max_periphs) { + err = -EINVAL ; +dev_err (&pdev->dev,"Unsupported APID count %d detected\n" , + pmic_arb->apid_count); + goto err_put_ctrl; + } + } + + pmic_arb->apid_data =devm_kcalloc (&ctrl->dev, pmic_arb->max_periphs, +sizeof (*pmic_arb->apid_data), +GFP_KERNEL ); +if (!pmic_arb->apid_data) { + err = -ENOMEM ; + goto err_put_ctrl; + } +dev_info (&ctrl->dev,"PMIC arbiter version %s (0x%x)\n" , pmic_arb->ver_ops->ver_str, hw_ver);@@ -1420,7 +1620,7 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev) } pmic_arb->ee = ee; - mapping_table =devm_kcalloc (&ctrl->dev,PMIC_ARB_MAX_PERIPHS , + mapping_table =devm_kcalloc (&ctrl->dev, pmic_arb->max_periphs,sizeof (*mapping_table),GFP_KERNEL );if (!mapping_table) { err = -ENOMEM ;@@ -1431,7 +1631,7 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)/* Initialize max_apid/min_apid to the opposite bounds, during * the irq domain translation, we are sure to update these */ pmic_arb->max_apid =0 ; - pmic_arb->min_apid =PMIC_ARB_MAX_PERIPHS -1 ; + pmic_arb->min_apid = pmic_arb->max_periphs -1 ;platform_set_drvdata (pdev, ctrl);raw_spin_lock_init (&pmic_arb->lock);Signature · 1 line
2.37.3
Quoted 4 lines · Vinod Koul
Hello,
The is version 5 of support for PMIC v7. I have added a new property qcom,bus-id for supporting v7 and then add driver changes for v7
Steve,
Can you please get this in for v6.1 ?
Quoted 22 lines
Changes since v4:
- Fix David name and email
- remove trailing line in bindingChanges since v3:
- rebase on spmi/nextDavid Collins (1):
spmi: pmic-arb: Add support for PMIC v7Vinod Koul (1):
dt-bindings: spmi: Add qcom,bus-id.../bindings/spmi/qcom,spmi-pmic-arb.yaml | 10 + drivers/spmi/spmi-pmic-arb.c | 242 ++++++++++++++++-- 2 files changed, 231 insertions(+), 21 deletions(-)base-commit:
18c42f8d23426d3f4048df89523aa47203c3493aSignature · 1 line
2.37.3
Signature · 1 line
~Vinod
Quoted 9 lines · Vinod Koul
Quoted 4 lines · Vinod Koul
Hello,
The is version 5 of support for PMIC v7. I have added a new property qcom,bus-id for supporting v7 and then add driver changes for v7
Steve,
Can you please get this in for v6.1 ?
I dont know what I can do now to get this patch in... looks like 6.1 is missed too!
Quoted 26 lines
Quoted 23 lines
Changes since v4:
- Fix David name and email
- remove trailing line in bindingChanges since v3:
- rebase on spmi/nextDavid Collins (1):
spmi: pmic-arb: Add support for PMIC v7Vinod Koul (1):
dt-bindings: spmi: Add qcom,bus-id.../bindings/spmi/qcom,spmi-pmic-arb.yaml | 10 + drivers/spmi/spmi-pmic-arb.c | 242 ++++++++++++++++-- 2 files changed, 231 insertions(+), 21 deletions(-)base-commit:
18c42f8d23426d3f4048df89523aa47203c3493aSignature · 1 line
2.37.3Signature · 1 line
~Vinod
Signature · 1 line
~Vinod
Quoted 4 lines · Vinod Koul
Hello,
The is version 5 of support for PMIC v7. I have added a new property qcom,bus-id for supporting v7 and then add driver changes for v7
Stephen,
Can you pick this? It has been so long...
Quoted 22 lines
Changes since v4:
- Fix David name and email
- remove trailing line in bindingChanges since v3:
- rebase on spmi/nextDavid Collins (1):
spmi: pmic-arb: Add support for PMIC v7Vinod Koul (1):
dt-bindings: spmi: Add qcom,bus-id.../bindings/spmi/qcom,spmi-pmic-arb.yaml | 10 + drivers/spmi/spmi-pmic-arb.c | 242 ++++++++++++++++-- 2 files changed, 231 insertions(+), 21 deletions(-)base-commit:
18c42f8d23426d3f4048df89523aa47203c3493aSignature · 1 line
2.37.3
Signature · 1 line
~Vinod
Quoted 8 lines · Vinod Koul
Quoted 4 lines · Vinod Koul
Hello,
The is version 5 of support for PMIC v7. I have added a new property qcom,bus-id for supporting v7 and then add driver changes for v7
Stephen,
Can you pick this? It has been so long...
Hi Stephen,
Do you mind looking at this? I've got some patches that depend on functionality here...
https://lore.kernel.org/all/[email protected]/
Thanks,
Melody
Quoted 21 lines
Quoted 21 lines
Changes since v4:
- Fix David name and email
- remove trailing line in bindingChanges since v3:
- rebase on spmi/nextDavid Collins (1):
spmi: pmic-arb: Add support for PMIC v7Vinod Koul (1):
dt-bindings: spmi: Add qcom,bus-id.../bindings/spmi/qcom,spmi-pmic-arb.yaml | 10 + drivers/spmi/spmi-pmic-arb.c | 242 ++++++++++++++++-- 2 files changed, 231 insertions(+), 21 deletions(-)base-commit:
18c42f8d23426d3f4048df89523aa47203c3493aSignature · 1 line
2.37.3
Quoted 8 lines · Melody Olvera
Quoted 5 lines · Vinod Koul
Quoted 4 lines · Vinod Koul
Hello,
The is version 5 of support for PMIC v7. I have added a new property qcom,bus-id for supporting v7 and then add driver changes for v7
Quoted 8 lines
Quoted 3 lines
Stephen,
Can you pick this? It has been so long...
Hi Stephen,
Do you mind looking at this? I've got some patches that depend on functionality here...
https://lore.kernel.org/all/[email protected]/
This was merged.
Best regards,
Krzysztof