Re: [PATCH v4] PCI: Add quirk for preventing bus reset on TI C667X

2021-04-19 Thread Kishon Vijay Abraham I



On 15/03/21 3:56 pm, Antti Järvinen wrote:
> Some TI KeyStone C667X devices do not support bus/hot reset. Its PCIESS
> automatically disables LTSSM when secondary bus reset is received and
> device stops working. Prevent bus reset by adding quirk_no_bus_reset to
> the device. With this change device can be assigned to VMs with VFIO,
> but it will leak state between VMs.
> 
> Reference: https://e2e.ti.com/support/processors/f/791/t/954382
> Signed-off-by: Antti Järvinen 

Reviewed-by: Kishon Vijay Abraham I 
> ---
>  drivers/pci/quirks.c | 10 ++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
> index 653660e3ba9e..d9201ad1ca39 100644
> --- a/drivers/pci/quirks.c
> +++ b/drivers/pci/quirks.c
> @@ -3578,6 +3578,16 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 
> 0x0034, quirk_no_bus_reset);
>   */
>  DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CAVIUM, 0xa100, quirk_no_bus_reset);
>  
> +/*
> + * Some TI keystone C667X devices do no support bus/hot reset.
> + * Its PCIESS automatically disables LTSSM when secondary bus reset is
> + * received and device stops working. Prevent bus reset by adding
> + * quirk_no_bus_reset to the device. With this change device can be
> + * assigned to VMs with VFIO, but it will leak state between VMs.
> + * Reference https://e2e.ti.com/support/processors/f/791/t/954382
> + */
> +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, 0xb005, quirk_no_bus_reset);
> +
>  static void quirk_no_pm_reset(struct pci_dev *dev)
>  {
>   /*
> 


[PATCH v5 7/7] Documentation: PCI: endpoint/pci-endpoint-cfs: Guide to use SR-IOV

2021-04-19 Thread Kishon Vijay Abraham I
Add Documentation to help users use PCI endpoint to create virtual
functions using configfs. An endpoint function is designated as a
virtual endpoint function device when it is linked to a physical
endpoint function device (instead of a endpoint controller).

Signed-off-by: Kishon Vijay Abraham I 
---
 Documentation/PCI/endpoint/pci-endpoint-cfs.rst | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/Documentation/PCI/endpoint/pci-endpoint-cfs.rst 
b/Documentation/PCI/endpoint/pci-endpoint-cfs.rst
index 696f8eeb4738..56fb33c5e8fd 100644
--- a/Documentation/PCI/endpoint/pci-endpoint-cfs.rst
+++ b/Documentation/PCI/endpoint/pci-endpoint-cfs.rst
@@ -43,6 +43,7 @@ entries corresponding to EPF driver will be created by the 
EPF core.
.. /
... /
... /
+   ... /
.. /
... /
... /
@@ -68,6 +69,7 @@ created)
... subsys_vendor_id
... subsys_id
... interrupt_pin
+   ... /
 ... primary/
... /
 ... secondary/
@@ -79,6 +81,13 @@ interface should be added in 'primary' directory and symlink 
of endpoint
 controller connected to secondary interface should be added in 'secondary'
 directory.
 
+The  directory can have a list of symbolic links
+() to other . These symbolic links should
+be created by the user to represent the virtual functions that are bound to
+the physical function. In the above directory structure  is a
+physical function and  is a virtual function. An EPF device once
+it's linked to another EPF device, cannot be linked to a EPC device.
+
 EPC Device
 ==
 
@@ -98,7 +107,8 @@ entries corresponding to EPC device will be created by the 
EPC core.
 
 The  directory will have a list of symbolic links to
 . These symbolic links should be created by the user to
-represent the functions present in the endpoint device.
+represent the functions present in the endpoint device. Only 
+that represents a physical function can be linked to a EPC device.
 
 The  directory will also have a *start* field. Once
 "1" is written to this field, the endpoint device will be ready to
-- 
2.17.1



[PATCH v5 6/7] misc: pci_endpoint_test: Populate sriov_configure ops to configure SR-IOV device

2021-04-19 Thread Kishon Vijay Abraham I
Populate sriov_configure ops with pci_sriov_configure_simple to
configure SR-IOV device.

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/misc/pci_endpoint_test.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c
index 1b2868ca4f2a..c7ee34013485 100644
--- a/drivers/misc/pci_endpoint_test.c
+++ b/drivers/misc/pci_endpoint_test.c
@@ -978,6 +978,7 @@ static struct pci_driver pci_endpoint_test_driver = {
.id_table   = pci_endpoint_test_tbl,
.probe  = pci_endpoint_test_probe,
.remove = pci_endpoint_test_remove,
+   .sriov_configure = pci_sriov_configure_simple,
 };
 module_pci_driver(pci_endpoint_test_driver);
 
-- 
2.17.1



[PATCH v5 4/7] PCI: endpoint: Add virtual function number in pci_epc ops

2021-04-19 Thread Kishon Vijay Abraham I
Add virtual function number in pci_epc ops. EPC controller driver
can perform virtual function specific initialization based on the
virtual function number.

Signed-off-by: Kishon Vijay Abraham I 
---
 .../pci/controller/cadence/pcie-cadence-ep.c  |  44 +++---
 .../pci/controller/dwc/pcie-designware-ep.c   |  36 ++---
 drivers/pci/controller/pcie-rcar-ep.c |  19 +--
 drivers/pci/controller/pcie-rockchip-ep.c |  18 +--
 drivers/pci/endpoint/functions/pci-epf-ntb.c  |  79 ++-
 drivers/pci/endpoint/functions/pci-epf-test.c |  66 +
 drivers/pci/endpoint/pci-epc-core.c   | 128 --
 drivers/pci/endpoint/pci-epf-core.c   |  48 ++-
 include/linux/pci-epc.h   |  57 
 9 files changed, 313 insertions(+), 182 deletions(-)

diff --git a/drivers/pci/controller/cadence/pcie-cadence-ep.c 
b/drivers/pci/controller/cadence/pcie-cadence-ep.c
index 897cdde02bd8..912a15be8bfd 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-ep.c
+++ b/drivers/pci/controller/cadence/pcie-cadence-ep.c
@@ -16,7 +16,7 @@
 #define CDNS_PCIE_EP_IRQ_PCI_ADDR_NONE 0x1
 #define CDNS_PCIE_EP_IRQ_PCI_ADDR_LEGACY   0x3
 
-static int cdns_pcie_ep_write_header(struct pci_epc *epc, u8 fn,
+static int cdns_pcie_ep_write_header(struct pci_epc *epc, u8 fn, u8 vfn,
 struct pci_epf_header *hdr)
 {
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
@@ -47,7 +47,7 @@ static int cdns_pcie_ep_write_header(struct pci_epc *epc, u8 
fn,
return 0;
 }
 
-static int cdns_pcie_ep_set_bar(struct pci_epc *epc, u8 fn,
+static int cdns_pcie_ep_set_bar(struct pci_epc *epc, u8 fn, u8 vfn,
struct pci_epf_bar *epf_bar)
 {
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
@@ -117,7 +117,7 @@ static int cdns_pcie_ep_set_bar(struct pci_epc *epc, u8 fn,
return 0;
 }
 
-static void cdns_pcie_ep_clear_bar(struct pci_epc *epc, u8 fn,
+static void cdns_pcie_ep_clear_bar(struct pci_epc *epc, u8 fn, u8 vfn,
   struct pci_epf_bar *epf_bar)
 {
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
@@ -147,8 +147,8 @@ static void cdns_pcie_ep_clear_bar(struct pci_epc *epc, u8 
fn,
epf->epf_bar[bar] = NULL;
 }
 
-static int cdns_pcie_ep_map_addr(struct pci_epc *epc, u8 fn, phys_addr_t addr,
-u64 pci_addr, size_t size)
+static int cdns_pcie_ep_map_addr(struct pci_epc *epc, u8 fn, u8 vfn,
+phys_addr_t addr, u64 pci_addr, size_t size)
 {
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
struct cdns_pcie *pcie = >pcie;
@@ -169,7 +169,7 @@ static int cdns_pcie_ep_map_addr(struct pci_epc *epc, u8 
fn, phys_addr_t addr,
return 0;
 }
 
-static void cdns_pcie_ep_unmap_addr(struct pci_epc *epc, u8 fn,
+static void cdns_pcie_ep_unmap_addr(struct pci_epc *epc, u8 fn, u8 vfn,
phys_addr_t addr)
 {
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
@@ -189,7 +189,7 @@ static void cdns_pcie_ep_unmap_addr(struct pci_epc *epc, u8 
fn,
clear_bit(r, >ob_region_map);
 }
 
-static int cdns_pcie_ep_set_msi(struct pci_epc *epc, u8 fn, u8 mmc)
+static int cdns_pcie_ep_set_msi(struct pci_epc *epc, u8 fn, u8 vfn, u8 mmc)
 {
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
struct cdns_pcie *pcie = >pcie;
@@ -209,7 +209,7 @@ static int cdns_pcie_ep_set_msi(struct pci_epc *epc, u8 fn, 
u8 mmc)
return 0;
 }
 
-static int cdns_pcie_ep_get_msi(struct pci_epc *epc, u8 fn)
+static int cdns_pcie_ep_get_msi(struct pci_epc *epc, u8 fn, u8 vfn)
 {
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
struct cdns_pcie *pcie = >pcie;
@@ -230,7 +230,7 @@ static int cdns_pcie_ep_get_msi(struct pci_epc *epc, u8 fn)
return mme;
 }
 
-static int cdns_pcie_ep_get_msix(struct pci_epc *epc, u8 func_no)
+static int cdns_pcie_ep_get_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no)
 {
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
struct cdns_pcie *pcie = >pcie;
@@ -247,8 +247,9 @@ static int cdns_pcie_ep_get_msix(struct pci_epc *epc, u8 
func_no)
return val;
 }
 
-static int cdns_pcie_ep_set_msix(struct pci_epc *epc, u8 fn, u16 interrupts,
-enum pci_barno bir, u32 offset)
+static int cdns_pcie_ep_set_msix(struct pci_epc *epc, u8 fn, u8 vfn,
+u16 interrupts, enum pci_barno bir,
+u32 offset)
 {
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
struct cdns_pcie *pcie = >pcie;
@@ -317,7 +318,8 @@ static void cdns_pcie_ep_assert_intx(struct cdns_pcie_ep 
*ep, u8 fn,
writel(0, ep->irq_cpu_addr + offset);
 }
 
-static int cdns_pcie_ep_send_legacy_irq(struct cdns_pcie_ep *ep, u8 fn, u8 
intx)
+static int cdns_pcie_ep_send_legacy_irq(struct cdns_pc

[PATCH v5 5/7] PCI: cadence: Add support to configure virtual functions

2021-04-19 Thread Kishon Vijay Abraham I
Now that support for SR-IOV is added in PCIe endpoint core, add support
to configure virtual functions in the Cadence PCIe EP driver.

Signed-off-by: Kishon Vijay Abraham I 
---
 .../pci/controller/cadence/pcie-cadence-ep.c  | 241 +++---
 drivers/pci/controller/cadence/pcie-cadence.h |   7 +
 2 files changed, 217 insertions(+), 31 deletions(-)

diff --git a/drivers/pci/controller/cadence/pcie-cadence-ep.c 
b/drivers/pci/controller/cadence/pcie-cadence-ep.c
index 912a15be8bfd..791915054ff4 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-ep.c
+++ b/drivers/pci/controller/cadence/pcie-cadence-ep.c
@@ -20,7 +20,18 @@ static int cdns_pcie_ep_write_header(struct pci_epc *epc, u8 
fn, u8 vfn,
 struct pci_epf_header *hdr)
 {
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
+   u32 cap = CDNS_PCIE_EP_FUNC_SRIOV_CAP_OFFSET;
struct cdns_pcie *pcie = >pcie;
+   u32 reg;
+
+   if (vfn > 1) {
+   dev_dbg(>dev, "Only Virtual Function #1 has deviceID\n");
+   return 0;
+   } else if (vfn == 1) {
+   reg = cap + PCI_SRIOV_VF_DID;
+   cdns_pcie_ep_fn_writew(pcie, fn, reg, hdr->deviceid);
+   return 0;
+   }
 
cdns_pcie_ep_fn_writew(pcie, fn, PCI_DEVICE_ID, hdr->deviceid);
cdns_pcie_ep_fn_writeb(pcie, fn, PCI_REVISION_ID, hdr->revid);
@@ -51,12 +62,14 @@ static int cdns_pcie_ep_set_bar(struct pci_epc *epc, u8 fn, 
u8 vfn,
struct pci_epf_bar *epf_bar)
 {
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
+   u32 cap = CDNS_PCIE_EP_FUNC_SRIOV_CAP_OFFSET;
struct cdns_pcie_epf *epf = >epf[fn];
struct cdns_pcie *pcie = >pcie;
dma_addr_t bar_phys = epf_bar->phys_addr;
enum pci_barno bar = epf_bar->barno;
int flags = epf_bar->flags;
u32 addr0, addr1, reg, cfg, b, aperture, ctrl;
+   u32 first_vf_offset, stride;
u64 sz;
 
/* BAR size is 2^(aperture + 7) */
@@ -92,26 +105,50 @@ static int cdns_pcie_ep_set_bar(struct pci_epc *epc, u8 
fn, u8 vfn,
 
addr0 = lower_32_bits(bar_phys);
addr1 = upper_32_bits(bar_phys);
+
+   if (vfn == 1) {
+   /* All virtual functions use the same BAR config */
+   if (bar < BAR_4) {
+   reg = CDNS_PCIE_LM_EP_VFUNC_BAR_CFG0(fn);
+   b = bar;
+   } else {
+   reg = CDNS_PCIE_LM_EP_VFUNC_BAR_CFG1(fn);
+   b = bar - BAR_4;
+   }
+   } else if (vfn == 0) {
+   /* BAR configuration for physical function */
+   if (bar < BAR_4) {
+   reg = CDNS_PCIE_LM_EP_FUNC_BAR_CFG0(fn);
+   b = bar;
+   } else {
+   reg = CDNS_PCIE_LM_EP_FUNC_BAR_CFG1(fn);
+   b = bar - BAR_4;
+   }
+   }
+
+   if (vfn == 0 || vfn == 1) {
+   cfg = cdns_pcie_readl(pcie, reg);
+   cfg &= ~(CDNS_PCIE_LM_EP_FUNC_BAR_CFG_BAR_APERTURE_MASK(b) |
+CDNS_PCIE_LM_EP_FUNC_BAR_CFG_BAR_CTRL_MASK(b));
+   cfg |= (CDNS_PCIE_LM_EP_FUNC_BAR_CFG_BAR_APERTURE(b, aperture) |
+   CDNS_PCIE_LM_EP_FUNC_BAR_CFG_BAR_CTRL(b, ctrl));
+   cdns_pcie_writel(pcie, reg, cfg);
+   }
+
+   if (vfn > 0) {
+   first_vf_offset = cdns_pcie_ep_fn_readw(pcie, fn, cap +
+   PCI_SRIOV_VF_OFFSET);
+   stride = cdns_pcie_ep_fn_readw(pcie, fn, cap +
+  PCI_SRIOV_VF_STRIDE);
+   fn = fn + first_vf_offset + ((vfn - 1) * stride);
+   epf = >epf[vfn - 1];
+   }
+
cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_EP_FUNC_BAR_ADDR0(fn, bar),
 addr0);
cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar),
 addr1);
 
-   if (bar < BAR_4) {
-   reg = CDNS_PCIE_LM_EP_FUNC_BAR_CFG0(fn);
-   b = bar;
-   } else {
-   reg = CDNS_PCIE_LM_EP_FUNC_BAR_CFG1(fn);
-   b = bar - BAR_4;
-   }
-
-   cfg = cdns_pcie_readl(pcie, reg);
-   cfg &= ~(CDNS_PCIE_LM_EP_FUNC_BAR_CFG_BAR_APERTURE_MASK(b) |
-CDNS_PCIE_LM_EP_FUNC_BAR_CFG_BAR_CTRL_MASK(b));
-   cfg |= (CDNS_PCIE_LM_EP_FUNC_BAR_CFG_BAR_APERTURE(b, aperture) |
-   CDNS_PCIE_LM_EP_FUNC_BAR_CFG_BAR_CTRL(b, ctrl));
-   cdns_pcie_writel(pcie, reg, cfg);
-
epf->epf_bar[bar] = epf_bar;
 
return 0;
@@ -121,25 +158,48 @@ static void cdns_pcie_ep_clear_bar(struct pci_epc *epc, 
u8 fn, u8 vfn,
   struct pci_epf_bar *epf_bar)
 {
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);

[PATCH v5 3/7] PCI: endpoint: Add support to link a physical function to a virtual function

2021-04-19 Thread Kishon Vijay Abraham I
While the physical function has to be linked to endpoint controller, the
virtual function has to be linked to a physical function. Add support to
link a physical function to a virtual function in pci-ep-cfs.

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/pci/endpoint/pci-ep-cfs.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/drivers/pci/endpoint/pci-ep-cfs.c 
b/drivers/pci/endpoint/pci-ep-cfs.c
index f3a8b833b479..11801877 100644
--- a/drivers/pci/endpoint/pci-ep-cfs.c
+++ b/drivers/pci/endpoint/pci-ep-cfs.c
@@ -475,6 +475,28 @@ static struct configfs_attribute *pci_epf_attrs[] = {
NULL,
 };
 
+static int pci_epf_vepf_link(struct config_item *epf_pf_item,
+struct config_item *epf_vf_item)
+{
+   struct pci_epf_group *epf_vf_group = to_pci_epf_group(epf_vf_item);
+   struct pci_epf_group *epf_pf_group = to_pci_epf_group(epf_pf_item);
+   struct pci_epf *epf_pf = epf_pf_group->epf;
+   struct pci_epf *epf_vf = epf_vf_group->epf;
+
+   return pci_epf_add_vepf(epf_pf, epf_vf);
+}
+
+static void pci_epf_vepf_unlink(struct config_item *epf_pf_item,
+   struct config_item *epf_vf_item)
+{
+   struct pci_epf_group *epf_vf_group = to_pci_epf_group(epf_vf_item);
+   struct pci_epf_group *epf_pf_group = to_pci_epf_group(epf_pf_item);
+   struct pci_epf *epf_pf = epf_pf_group->epf;
+   struct pci_epf *epf_vf = epf_vf_group->epf;
+
+   pci_epf_remove_vepf(epf_pf, epf_vf);
+}
+
 static void pci_epf_release(struct config_item *item)
 {
struct pci_epf_group *epf_group = to_pci_epf_group(item);
@@ -487,6 +509,8 @@ static void pci_epf_release(struct config_item *item)
 }
 
 static struct configfs_item_operations pci_epf_ops = {
+   .allow_link = pci_epf_vepf_link,
+   .drop_link  = pci_epf_vepf_unlink,
.release= pci_epf_release,
 };
 
-- 
2.17.1



[PATCH v5 0/7] Add SR-IOV support in PCIe Endpoint Core

2021-04-19 Thread Kishon Vijay Abraham I
Patch series
*) Adds support to add virtual functions to enable endpoint controller
   which supports SR-IOV capability
*) Add support in Cadence endpoint driver to configure virtual functions
*) Enable pci_endpoint_test driver to create pci_device for virtual
   functions

v1 of the patch series can be found at [1]
v2 of the patch series can be found at [2]
v3 of the patch series can be found at [3]
v4 of the patch series can be found at [4]

Here both physical functions and virtual functions use the same
pci_endpoint_test driver and existing pcitest utility can be used
to test virtual functions as well.

Changes from v4:
*) Added a fix in Cadence driver which was overwriting BAR configuration
   of physical function.
*) Didn't include Tom's Acked-by since Cadence driver is modified in
   this revision.

Changes from v3:
*) Fixed Rob's comment and added his Reviewed-by as suggested by him.

Changes from v2:
*) Fixed DT binding documentation comment by Rob
*) Fixed the error check in pci-epc-core.c

Changes from v1:
*) Re-based and Re-worked to latest kernel 5.10.0-rc2+ (now has generic
   binding for EP)

[1] -> http://lore.kernel.org/r/20191231113534.30405-1-kis...@ti.com
[2] -> http://lore.kernel.org/r/20201112175358.2653-1-kis...@ti.com
[3] -> https://lore.kernel.org/r/20210305050410.9201-1-kis...@ti.com
[4] -> http://lore.kernel.org/r/20210310160943.7606-1-kis...@ti.com

Kishon Vijay Abraham I (7):
  dt-bindings: PCI: pci-ep: Add binding to specify virtual function
  PCI: endpoint: Add support to add virtual function in endpoint core
  PCI: endpoint: Add support to link a physical function to a virtual
function
  PCI: endpoint: Add virtual function number in pci_epc ops
  PCI: cadence: Add support to configure virtual functions
  misc: pci_endpoint_test: Populate sriov_configure ops to configure
SR-IOV device
  Documentation: PCI: endpoint/pci-endpoint-cfs: Guide to use SR-IOV

 .../PCI/endpoint/pci-endpoint-cfs.rst |  12 +-
 .../devicetree/bindings/pci/pci-ep.yaml   |   7 +
 drivers/misc/pci_endpoint_test.c  |   1 +
 .../pci/controller/cadence/pcie-cadence-ep.c  | 285 ++
 drivers/pci/controller/cadence/pcie-cadence.h |   7 +
 .../pci/controller/dwc/pcie-designware-ep.c   |  36 +--
 drivers/pci/controller/pcie-rcar-ep.c |  19 +-
 drivers/pci/controller/pcie-rockchip-ep.c |  18 +-
 drivers/pci/endpoint/functions/pci-epf-ntb.c  |  79 +++--
 drivers/pci/endpoint/functions/pci-epf-test.c |  66 ++--
 drivers/pci/endpoint/pci-ep-cfs.c |  24 ++
 drivers/pci/endpoint/pci-epc-core.c   | 130 +---
 drivers/pci/endpoint/pci-epf-core.c   | 144 -
 include/linux/pci-epc.h   |  57 ++--
 include/linux/pci-epf.h   |  16 +-
 15 files changed, 684 insertions(+), 217 deletions(-)

-- 
2.17.1



[PATCH v5 2/7] PCI: endpoint: Add support to add virtual function in endpoint core

2021-04-19 Thread Kishon Vijay Abraham I
Add support to add virtual function in endpoint core. The virtual
function can only be associated with a physical function instead of a
endpoint controller. Provide APIs to associate a virtual function with
a physical function here.

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/pci/endpoint/pci-epc-core.c |  2 +-
 drivers/pci/endpoint/pci-epf-core.c | 96 -
 include/linux/pci-epf.h | 16 -
 3 files changed, 111 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/endpoint/pci-epc-core.c 
b/drivers/pci/endpoint/pci-epc-core.c
index cc8f9eb2b177..fe6d23849502 100644
--- a/drivers/pci/endpoint/pci-epc-core.c
+++ b/drivers/pci/endpoint/pci-epc-core.c
@@ -548,7 +548,7 @@ int pci_epc_add_epf(struct pci_epc *epc, struct pci_epf 
*epf,
u32 func_no;
int ret = 0;
 
-   if (IS_ERR_OR_NULL(epc))
+   if (IS_ERR_OR_NULL(epc) || epf->is_vf)
return -EINVAL;
 
if (type == PRIMARY_INTERFACE && epf->epc)
diff --git a/drivers/pci/endpoint/pci-epf-core.c 
b/drivers/pci/endpoint/pci-epf-core.c
index 7646c8660d42..3f1271a63be5 100644
--- a/drivers/pci/endpoint/pci-epf-core.c
+++ b/drivers/pci/endpoint/pci-epf-core.c
@@ -62,13 +62,20 @@ EXPORT_SYMBOL_GPL(pci_epf_type_add_cfs);
  */
 void pci_epf_unbind(struct pci_epf *epf)
 {
+   struct pci_epf *epf_vf;
+
if (!epf->driver) {
dev_WARN(>dev, "epf device not bound to driver\n");
return;
}
 
mutex_lock(>lock);
-   epf->driver->ops->unbind(epf);
+   list_for_each_entry(epf_vf, >pci_vepf, list) {
+   if (epf_vf->is_bound)
+   epf_vf->driver->ops->unbind(epf_vf);
+   }
+   if (epf->is_bound)
+   epf->driver->ops->unbind(epf);
mutex_unlock(>lock);
module_put(epf->driver->owner);
 }
@@ -83,6 +90,7 @@ EXPORT_SYMBOL_GPL(pci_epf_unbind);
  */
 int pci_epf_bind(struct pci_epf *epf)
 {
+   struct pci_epf *epf_vf;
int ret;
 
if (!epf->driver) {
@@ -94,13 +102,95 @@ int pci_epf_bind(struct pci_epf *epf)
return -EAGAIN;
 
mutex_lock(>lock);
+   list_for_each_entry(epf_vf, >pci_vepf, list) {
+   epf_vf->func_no = epf->func_no;
+   epf_vf->epc = epf->epc;
+   epf_vf->sec_epc = epf->sec_epc;
+   ret = epf_vf->driver->ops->bind(epf_vf);
+   if (ret)
+   goto ret;
+   epf_vf->is_bound = true;
+   }
+
ret = epf->driver->ops->bind(epf);
+   if (ret)
+   goto ret;
+   epf->is_bound = true;
+
+   mutex_unlock(>lock);
+   return 0;
+
+ret:
mutex_unlock(>lock);
+   pci_epf_unbind(epf);
 
return ret;
 }
 EXPORT_SYMBOL_GPL(pci_epf_bind);
 
+/**
+ * pci_epf_add_vepf() - associate virtual EP function to physical EP function
+ * @epf_pf: the physical EP function to which the virtual EP function should be
+ *   associated
+ * @epf_vf: the virtual EP function to be added
+ *
+ * A physical endpoint function can be associated with multiple virtual
+ * endpoint functions. Invoke pci_epf_add_epf() to add a virtual PCI endpoint
+ * function to a physical PCI endpoint function.
+ */
+int pci_epf_add_vepf(struct pci_epf *epf_pf, struct pci_epf *epf_vf)
+{
+   u32 vfunc_no;
+
+   if (IS_ERR_OR_NULL(epf_pf) || IS_ERR_OR_NULL(epf_vf))
+   return -EINVAL;
+
+   if (epf_pf->epc || epf_vf->epc || epf_vf->epf_pf)
+   return -EBUSY;
+
+   if (epf_pf->sec_epc || epf_vf->sec_epc)
+   return -EBUSY;
+
+   mutex_lock(_pf->lock);
+   vfunc_no = find_first_zero_bit(_pf->vfunction_num_map,
+  BITS_PER_LONG);
+   if (vfunc_no >= BITS_PER_LONG)
+   return -EINVAL;
+
+   set_bit(vfunc_no, _pf->vfunction_num_map);
+   epf_vf->vfunc_no = vfunc_no;
+
+   epf_vf->epf_pf = epf_pf;
+   epf_vf->is_vf = true;
+
+   list_add_tail(_vf->list, _pf->pci_vepf);
+   mutex_unlock(_pf->lock);
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(pci_epf_add_vepf);
+
+/**
+ * pci_epf_remove_vepf() - remove virtual EP function from physical EP function
+ * @epf_pf: the physical EP function from which the virtual EP function should
+ *   be removed
+ * @epf_vf: the virtual EP function to be removed
+ *
+ * Invoke to remove a virtual endpoint function from the physcial endpoint
+ * function.
+ */
+void pci_epf_remove_vepf(struct pci_epf *epf_pf, struct pci_epf *epf_vf)
+{
+   if (IS_ERR_OR_NULL(epf_pf) || IS_ERR_OR_NULL(epf_vf))
+   return;
+
+   mutex_lock(_pf->lock);
+   clear_bit(epf_vf->vfunc_no, _pf->vfunction_num_map);
+   list_del(_vf->list);
+   mutex_unlock(_pf->lock);
+}
+EX

[PATCH v5 1/7] dt-bindings: PCI: pci-ep: Add binding to specify virtual function

2021-04-19 Thread Kishon Vijay Abraham I
Add binding to specify virtual function (associated with each physical
function) in endpoint mode.

Signed-off-by: Kishon Vijay Abraham I 
Reviewed-by: Rob Herring 
---
 Documentation/devicetree/bindings/pci/pci-ep.yaml | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/Documentation/devicetree/bindings/pci/pci-ep.yaml 
b/Documentation/devicetree/bindings/pci/pci-ep.yaml
index 7847bbcd4a03..ccec51ab5247 100644
--- a/Documentation/devicetree/bindings/pci/pci-ep.yaml
+++ b/Documentation/devicetree/bindings/pci/pci-ep.yaml
@@ -23,6 +23,13 @@ properties:
 default: 1
 maximum: 255
 
+  max-virtual-functions:
+description: Array representing the number of virtual functions 
corresponding to each physical
+  function
+$ref: /schemas/types.yaml#/definitions/uint8-array
+minItems: 1
+maxItems: 255
+
   max-link-speed:
 $ref: /schemas/types.yaml#/definitions/uint32
 enum: [ 1, 2, 3, 4 ]
-- 
2.17.1



Re: [PATCH v3 2/4] phy: Add API for devm_of_phy_optional_get_by_index

2021-04-15 Thread Kishon Vijay Abraham I
Hi Aswath,

On 15/04/21 8:19 pm, Aswath Govindraju wrote:
> Add API for devm_of_phy_optional_get_by_index, to obtain a reference to an
> optional phy by index.

Rob has posted a patch
http://lore.kernel.org/r/20210414135525.3535787-1-r...@kernel.org
that doesn't require consumers to get a phy by using string. Since your
usecase also requires only one PHY, that patch should be sufficient.
$patch could be deferred until a real use case comes.

Thanks
Kishon

> 
> Signed-off-by: Aswath Govindraju 
> ---
>  drivers/phy/phy-core.c  | 26 ++
>  include/linux/phy/phy.h |  2 ++
>  2 files changed, 28 insertions(+)
> 
> diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
> index ccb575b13777..bf06d4e0ede2 100644
> --- a/drivers/phy/phy-core.c
> +++ b/drivers/phy/phy-core.c
> @@ -839,6 +839,32 @@ struct phy *devm_of_phy_get(struct device *dev, struct 
> device_node *np,
>  }
>  EXPORT_SYMBOL_GPL(devm_of_phy_get);
>  
> +/**
> + * devm_of_phy_optional_get_by_index() - lookup and obtain a reference to an 
> optional phy by index.
> + * @dev: device that requests this phy
> + * @np: node containing the phy
> + * @index: index of the phy
> + *
> + * Gets the phy using _of_phy_get(), then gets a refcount to it,
> + * and associates a device with it using devres. On driver detach,
> + * release function is invoked on the devres data, then,
> + * devres data is freed. This differs to devm_of_phy_get_by_index() in
> + * that if the phy does not exist, it is not considered an error and
> + * -ENODEV will not be returned. Instead the NULL phy is returned,
> + * which can be passed to all other phy consumer calls.
> + */
> +struct phy *devm_of_phy_optional_get_by_index(struct device *dev, struct 
> device_node *np,
> +   int index)
> +{
> + struct phy *phy = devm_of_phy_get_by_index(dev, np, index);
> +
> + if (PTR_ERR(phy) == -ENODEV)
> + phy = NULL;
> +
> + return phy;
> +}
> +EXPORT_SYMBOL_GPL(devm_of_phy_optional_get_by_index);
> +
>  /**
>   * devm_of_phy_get_by_index() - lookup and obtain a reference to a phy by 
> index.
>   * @dev: device that requests this phy
> diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
> index f3286f4cd306..c5f32b4fadd6 100644
> --- a/include/linux/phy/phy.h
> +++ b/include/linux/phy/phy.h
> @@ -253,6 +253,8 @@ struct phy *devm_of_phy_get(struct device *dev, struct 
> device_node *np,
>   const char *con_id);
>  struct phy *devm_of_phy_get_by_index(struct device *dev, struct device_node 
> *np,
>int index);
> +struct phy *devm_of_phy_optional_get_by_index(struct device *dev, struct 
> device_node *np,
> +   int index);
>  void of_phy_put(struct phy *phy);
>  void phy_put(struct device *dev, struct phy *phy);
>  void devm_phy_put(struct device *dev, struct phy *phy);
> 


Re: [Discussion] Uninitialized variable in wiz_mode_select()

2021-04-01 Thread Kishon Vijay Abraham I
Hi,

On 01/04/21 1:08 pm, Kishon Vijay Abraham I wrote:
> Hi Usama,
> 
> On 01/04/21 1:03 pm, Muhammad Usama Anjum wrote:
>> Hi,
>>
>> `mode` remains uninitialized when `lane_phy_type` isn't PHY_TYPE_DP
>> or 
>> PHY_TYPE_QSGMII. I've checked the dtsi (k3-j721e-common-proc-
>> board.dts) 
>> and possible values of `lane_phy_type` are justPHY_TYPE_USB3 and 
>> PHY_TYPE_PCIE. If this is correct, the mode will remain uninitialized with
>> garbage value. `mode` should be initialized to what? It seems like it is 
>> highly 
>> implementation dependent.
>>
>> /drivers/phy/ti/phy-j721e-wiz.c: 344 in wiz_mode_select()
>> 338 for (i = 0; i < num_lanes; i++) {
>> 339 if (wiz->lane_phy_type[i] == PHY_TYPE_DP)
>> 340 mode = LANE_MODE_GEN1;
>> 341 else if (wiz->lane_phy_type[i] == PHY_TYPE_QSGMII)
>> 342 mode = LANE_MODE_GEN2;
>> 343 
>>>>> CID 1503592:  Uninitialized variables  (UNINIT)
>>>>> Using uninitialized value "mode" when calling "regmap_field_write".
>> 344 ret = regmap_field_write(wiz->p_standard_mode[i], 
>> mode);
>> 345 if (ret)
>> 346 return ret;
>> 347 }
>> 348 
>> 349 return 0;
> 
> I've sent a follow-up patch fixing this.
> http://lor.kernel.org/r/20210331131417.15596-1-kis...@ti.com

Fixed a typo in the link
https://lore.kernel.org/linux-phy/20210331131417.15596-1-kis...@ti.com/

Thanks
Kishon


Re: [Discussion] Uninitialized variable in wiz_mode_select()

2021-04-01 Thread Kishon Vijay Abraham I
Hi Usama,

On 01/04/21 1:03 pm, Muhammad Usama Anjum wrote:
> Hi,
> 
> `mode` remains uninitialized when `lane_phy_type` isn't PHY_TYPE_DP
> or 
> PHY_TYPE_QSGMII. I've checked the dtsi (k3-j721e-common-proc-
> board.dts) 
> and possible values of `lane_phy_type` are justPHY_TYPE_USB3 and 
> PHY_TYPE_PCIE. If this is correct, the mode will remain uninitialized with
> garbage value. `mode` should be initialized to what? It seems like it is 
> highly 
> implementation dependent.
> 
> /drivers/phy/ti/phy-j721e-wiz.c: 344 in wiz_mode_select()
> 338 for (i = 0; i < num_lanes; i++) {
> 339 if (wiz->lane_phy_type[i] == PHY_TYPE_DP)
> 340 mode = LANE_MODE_GEN1;
> 341 else if (wiz->lane_phy_type[i] == PHY_TYPE_QSGMII)
> 342 mode = LANE_MODE_GEN2;
> 343 
 CID 1503592:  Uninitialized variables  (UNINIT)
 Using uninitialized value "mode" when calling "regmap_field_write".
> 344 ret = regmap_field_write(wiz->p_standard_mode[i], 
> mode);
> 345 if (ret)
> 346 return ret;
> 347 }
> 348 
> 349 return 0;

I've sent a follow-up patch fixing this.
http://lor.kernel.org/r/20210331131417.15596-1-kis...@ti.com

Thanks
Kishon


Re: [PATCH v5 2/5] phy: Add LVDS configuration options

2021-03-31 Thread Kishon Vijay Abraham I
Hi,

On 25/03/21 2:30 pm, Liu Ying wrote:
> This patch allows LVDS PHYs to be configured through
> the generic functions and through a custom structure
> added to the generic union.
> 
> The parameters added here are based on common LVDS PHY
> implementation practices.  The set of parameters
> should cover all potential users.
> 
> Cc: Kishon Vijay Abraham I 
> Cc: Vinod Koul 
> Cc: NXP Linux Team 
> Signed-off-by: Liu Ying 
> ---
> v4->v5:
> * Align kernel-doc style to include/linux/phy/phy.h. (Vinod)
> * Trivial tweaks.
> * Drop Robert's R-b tag.
> 
> v3->v4:
> * Add Robert's R-b tag.
> 
> v2->v3:
> * No change.
> 
> v1->v2:
> * No change.
> 
>  include/linux/phy/phy-lvds.h | 32 
>  include/linux/phy/phy.h  |  4 
>  2 files changed, 36 insertions(+)
>  create mode 100644 include/linux/phy/phy-lvds.h
> 
> diff --git a/include/linux/phy/phy-lvds.h b/include/linux/phy/phy-lvds.h
> new file mode 100644
> index ..7a2f474
> --- /dev/null
> +++ b/include/linux/phy/phy-lvds.h
> @@ -0,0 +1,32 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright 2020 NXP
> + */
> +
> +#ifndef __PHY_LVDS_H_
> +#define __PHY_LVDS_H_
> +
> +/**
> + * struct phy_configure_opts_lvds - LVDS configuration set
> + * @bits_per_lane_and_dclk_cycle:Number of bits per data lane and
> + *   differential clock cycle.

phy_set_bus_width() instead?
> + * @differential_clk_rate:   Clock rate, in Hertz, of the LVDS
> + *   differential clock.

Please use clk API's to get rate.
> + * @lanes:   Number of active, consecutive,
> + *   data lanes, starting from lane 0,
> + *   used for the transmissions.
> + * @is_slave:Boolean, true if the phy is a 
> slave
> + *   which works together with a master
> + *   phy to support dual link transmission,
> + *   otherwise a regular phy or a master phy.

For parameters that are known at design time, it doesn't have to be
passed from consumer driver. So all these parameters do they really have
to be passed at runtime?

Thanks
Kishon
> + *
> + * This structure is used to represent the configuration state of a LVDS phy.
> + */
> +struct phy_configure_opts_lvds {
> + unsigned intbits_per_lane_and_dclk_cycle;
> + unsigned long   differential_clk_rate;
> + unsigned intlanes;
> + boolis_slave;
> +};
> +
> +#endif /* __PHY_LVDS_H_ */
> diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
> index e435bdb..d450b44 100644
> --- a/include/linux/phy/phy.h
> +++ b/include/linux/phy/phy.h
> @@ -17,6 +17,7 @@
>  #include 
>  
>  #include 
> +#include 
>  #include 
>  
>  struct phy;
> @@ -51,10 +52,13 @@ enum phy_mode {
>   *   the MIPI_DPHY phy mode.
>   * @dp:  Configuration set applicable for phys supporting
>   *   the DisplayPort protocol.
> + * @lvds:Configuration set applicable for phys supporting
> + *   the LVDS phy mode.
>   */
>  union phy_configure_opts {
>   struct phy_configure_opts_mipi_dphy mipi_dphy;
>   struct phy_configure_opts_dpdp;
> + struct phy_configure_opts_lvds  lvds;
>  };
>  
>  /**
> 


[PATCH] phy: ti: j721e-wiz: Configure 'p_standard_mode' only for DP/QSGMII

2021-03-31 Thread Kishon Vijay Abraham I
Configure 'p_standard_mode' only for DP/QSGMII as for other modes
it's not used as per the programming sequence. Add "continue" in the
else to prevent random value from being written to p_standard_mode.

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/phy/ti/phy-j721e-wiz.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c
index 95905e5c4f3d..fc636233dbd6 100644
--- a/drivers/phy/ti/phy-j721e-wiz.c
+++ b/drivers/phy/ti/phy-j721e-wiz.c
@@ -340,6 +340,8 @@ static int wiz_mode_select(struct wiz *wiz)
mode = LANE_MODE_GEN1;
else if (wiz->lane_phy_type[i] == PHY_TYPE_QSGMII)
mode = LANE_MODE_GEN2;
+   else
+   continue;
 
ret = regmap_field_write(wiz->p_standard_mode[i], mode);
if (ret)
-- 
2.17.1



[PATCH v2 3/5] phy: cadence-torrent: Do not configure SERDES if it's already configured

2021-03-30 Thread Kishon Vijay Abraham I
Do not configure torrent SERDES if it's already configured.

Signed-off-by: Kishon Vijay Abraham I 
Reviewed-by: Swapnil Jakhade 
---
 drivers/phy/cadence/phy-cadence-torrent.c | 32 ---
 1 file changed, 22 insertions(+), 10 deletions(-)

diff --git a/drivers/phy/cadence/phy-cadence-torrent.c 
b/drivers/phy/cadence/phy-cadence-torrent.c
index ab51c4bf7b30..5ee1657f5a1c 100644
--- a/drivers/phy/cadence/phy-cadence-torrent.c
+++ b/drivers/phy/cadence/phy-cadence-torrent.c
@@ -371,6 +371,10 @@ static const struct phy_ops cdns_torrent_phy_ops = {
.owner  = THIS_MODULE,
 };
 
+static const struct phy_ops noop_ops = {
+   .owner  = THIS_MODULE,
+};
+
 struct cdns_reg_pairs {
u32 val;
u32 off;
@@ -2306,6 +2310,7 @@ static int cdns_torrent_phy_probe(struct platform_device 
*pdev)
struct device_node *child;
int ret, subnodes, node = 0, i;
u32 total_num_lanes = 0;
+   int already_configured;
u8 init_dp_regmap = 0;
u32 phy_type;
 
@@ -2344,16 +2349,20 @@ static int cdns_torrent_phy_probe(struct 
platform_device *pdev)
if (ret)
return ret;
 
-   ret = cdns_torrent_reset(cdns_phy);
-   if (ret)
-   goto clk_cleanup;
+   regmap_field_read(cdns_phy->phy_pma_cmn_ctrl_1, _configured);
 
-   ret = cdns_torrent_clk(cdns_phy);
-   if (ret)
-   goto clk_cleanup;
+   if (!already_configured) {
+   ret = cdns_torrent_reset(cdns_phy);
+   if (ret)
+   goto clk_cleanup;
+
+   ret = cdns_torrent_clk(cdns_phy);
+   if (ret)
+   goto clk_cleanup;
 
-   /* Enable APB */
-   reset_control_deassert(cdns_phy->apb_rst);
+   /* Enable APB */
+   reset_control_deassert(cdns_phy->apb_rst);
+   }
 
for_each_available_child_of_node(dev->of_node, child) {
struct phy *gphy;
@@ -2423,7 +2432,10 @@ static int cdns_torrent_phy_probe(struct platform_device 
*pdev)
of_property_read_u32(child, "cdns,ssc-mode",
 _phy->phys[node].ssc_mode);
 
-   gphy = devm_phy_create(dev, child, _torrent_phy_ops);
+   if (!already_configured)
+   gphy = devm_phy_create(dev, child, 
_torrent_phy_ops);
+   else
+   gphy = devm_phy_create(dev, child, _ops);
if (IS_ERR(gphy)) {
ret = PTR_ERR(gphy);
goto put_child;
@@ -2507,7 +2519,7 @@ static int cdns_torrent_phy_probe(struct platform_device 
*pdev)
goto put_lnk_rst;
}
 
-   if (cdns_phy->nsubnodes > 1) {
+   if (cdns_phy->nsubnodes > 1 && !already_configured) {
ret = cdns_torrent_phy_configure_multilink(cdns_phy);
if (ret)
goto put_lnk_rst;
-- 
2.17.1



[PATCH v2 2/5] phy: cadence-torrent: Group reset APIs and clock APIs

2021-03-30 Thread Kishon Vijay Abraham I
No functional change intended. Group reset APIs and clock APIs in
preparation for adding support to skip configuration if the SERDES
is already configured by bootloader.

Signed-off-by: Kishon Vijay Abraham I 
Reviewed-by: Swapnil Jakhade 
---
 drivers/phy/cadence/phy-cadence-torrent.c | 84 ++-
 1 file changed, 53 insertions(+), 31 deletions(-)

diff --git a/drivers/phy/cadence/phy-cadence-torrent.c 
b/drivers/phy/cadence/phy-cadence-torrent.c
index 3fdab0d288c4..ab51c4bf7b30 100644
--- a/drivers/phy/cadence/phy-cadence-torrent.c
+++ b/drivers/phy/cadence/phy-cadence-torrent.c
@@ -2249,6 +2249,54 @@ static int cdns_torrent_clk_register(struct 
cdns_torrent_phy *cdns_phy)
return 0;
 }
 
+static int cdns_torrent_reset(struct cdns_torrent_phy *cdns_phy)
+{
+   struct device *dev = cdns_phy->dev;
+
+   cdns_phy->phy_rst = devm_reset_control_get_exclusive_by_index(dev, 0);
+   if (IS_ERR(cdns_phy->phy_rst)) {
+   dev_err(dev, "%s: failed to get reset\n",
+   dev->of_node->full_name);
+   return PTR_ERR(cdns_phy->phy_rst);
+   }
+
+   cdns_phy->apb_rst = devm_reset_control_get_optional(dev, "torrent_apb");
+   if (IS_ERR(cdns_phy->apb_rst)) {
+   dev_err(dev, "%s: failed to get apb reset\n",
+   dev->of_node->full_name);
+   return PTR_ERR(cdns_phy->apb_rst);
+   }
+
+   return 0;
+}
+
+static int cdns_torrent_clk(struct cdns_torrent_phy *cdns_phy)
+{
+   struct device *dev = cdns_phy->dev;
+   int ret;
+
+   cdns_phy->clk = devm_clk_get(dev, "refclk");
+   if (IS_ERR(cdns_phy->clk)) {
+   dev_err(dev, "phy ref clock not found\n");
+   return PTR_ERR(cdns_phy->clk);
+   }
+
+   ret = clk_prepare_enable(cdns_phy->clk);
+   if (ret) {
+   dev_err(cdns_phy->dev, "Failed to prepare ref clock\n");
+   return ret;
+   }
+
+   cdns_phy->ref_clk_rate = clk_get_rate(cdns_phy->clk);
+   if (!(cdns_phy->ref_clk_rate)) {
+   dev_err(cdns_phy->dev, "Failed to get ref clock rate\n");
+   clk_disable_unprepare(cdns_phy->clk);
+   return -EINVAL;
+   }
+
+   return 0;
+}
+
 static int cdns_torrent_phy_probe(struct platform_device *pdev)
 {
struct cdns_torrent_phy *cdns_phy;
@@ -2274,26 +2322,6 @@ static int cdns_torrent_phy_probe(struct platform_device 
*pdev)
cdns_phy->dev = dev;
cdns_phy->init_data = data;
 
-   cdns_phy->phy_rst = devm_reset_control_get_exclusive_by_index(dev, 0);
-   if (IS_ERR(cdns_phy->phy_rst)) {
-   dev_err(dev, "%s: failed to get reset\n",
-   dev->of_node->full_name);
-   return PTR_ERR(cdns_phy->phy_rst);
-   }
-
-   cdns_phy->apb_rst = devm_reset_control_get_optional(dev, "torrent_apb");
-   if (IS_ERR(cdns_phy->apb_rst)) {
-   dev_err(dev, "%s: failed to get apb reset\n",
-   dev->of_node->full_name);
-   return PTR_ERR(cdns_phy->apb_rst);
-   }
-
-   cdns_phy->clk = devm_clk_get(dev, "refclk");
-   if (IS_ERR(cdns_phy->clk)) {
-   dev_err(dev, "phy ref clock not found\n");
-   return PTR_ERR(cdns_phy->clk);
-   }
-
cdns_phy->sd_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(cdns_phy->sd_base))
return PTR_ERR(cdns_phy->sd_base);
@@ -2316,18 +2344,13 @@ static int cdns_torrent_phy_probe(struct 
platform_device *pdev)
if (ret)
return ret;
 
-   ret = clk_prepare_enable(cdns_phy->clk);
-   if (ret) {
-   dev_err(cdns_phy->dev, "Failed to prepare ref clock\n");
+   ret = cdns_torrent_reset(cdns_phy);
+   if (ret)
goto clk_cleanup;
-   }
 
-   cdns_phy->ref_clk_rate = clk_get_rate(cdns_phy->clk);
-   if (!(cdns_phy->ref_clk_rate)) {
-   dev_err(cdns_phy->dev, "Failed to get ref clock rate\n");
-   ret = -EINVAL;
-   goto clk_disable;
-   }
+   ret = cdns_torrent_clk(cdns_phy);
+   if (ret)
+   goto clk_cleanup;
 
/* Enable APB */
reset_control_deassert(cdns_phy->apb_rst);
@@ -2505,7 +2528,6 @@ static int cdns_torrent_phy_probe(struct platform_device 
*pdev)
reset_control_put(cdns_phy->phys[i].lnk_rst);
of_node_put(child);
reset_control_assert(cdns_phy->apb_rst);
-clk_disable:
clk_disable_unprepare(cdns_phy->clk);
 clk_cleanup:
cdns_torrent_clk_cleanup(cdns_phy);
-- 
2.17.1



[PATCH v2 5/5] phy: cadence-torrent: Add delay for PIPE clock to be stable

2021-03-30 Thread Kishon Vijay Abraham I
The Torrent spec specifies delay of 660.5us after phy_reset is
asserted by the controller. To be on the safe side provide a delay
of 5ms to 10ms in ->phy_on() callback where the SERDES is already
configured in bootloader.

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/phy/cadence/phy-cadence-torrent.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/phy/cadence/phy-cadence-torrent.c 
b/drivers/phy/cadence/phy-cadence-torrent.c
index ff8bb4b724c0..0477e7beebbf 100644
--- a/drivers/phy/cadence/phy-cadence-torrent.c
+++ b/drivers/phy/cadence/phy-cadence-torrent.c
@@ -371,7 +371,16 @@ static const struct phy_ops cdns_torrent_phy_ops = {
.owner  = THIS_MODULE,
 };
 
+static int cdns_torrent_noop_phy_on(struct phy *phy)
+{
+   /* Give 5ms to 10ms delay for the PIPE clock to be stable */
+   usleep_range(5000, 1);
+
+   return 0;
+}
+
 static const struct phy_ops noop_ops = {
+   .power_on   = cdns_torrent_noop_phy_on,
.owner  = THIS_MODULE,
 };
 
-- 
2.17.1



[PATCH v2 4/5] phy: cadence-torrent: Explicitly request exclusive reset control

2021-03-30 Thread Kishon Vijay Abraham I
No functional change. Since the reset controls obtained in
Torrent is exclusively used by the Torrent device, use
exclusive reset control request API calls.

Signed-off-by: Kishon Vijay Abraham I 
Reviewed-by: Swapnil Jakhade 
---
 drivers/phy/cadence/phy-cadence-torrent.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/phy/cadence/phy-cadence-torrent.c 
b/drivers/phy/cadence/phy-cadence-torrent.c
index 5ee1657f5a1c..ff8bb4b724c0 100644
--- a/drivers/phy/cadence/phy-cadence-torrent.c
+++ b/drivers/phy/cadence/phy-cadence-torrent.c
@@ -2264,7 +2264,7 @@ static int cdns_torrent_reset(struct cdns_torrent_phy 
*cdns_phy)
return PTR_ERR(cdns_phy->phy_rst);
}
 
-   cdns_phy->apb_rst = devm_reset_control_get_optional(dev, "torrent_apb");
+   cdns_phy->apb_rst = devm_reset_control_get_optional_exclusive(dev, 
"torrent_apb");
if (IS_ERR(cdns_phy->apb_rst)) {
dev_err(dev, "%s: failed to get apb reset\n",
dev->of_node->full_name);
-- 
2.17.1



[PATCH v2 1/5] phy: ti: j721e-wiz: Do not configure wiz if its already configured

2021-03-30 Thread Kishon Vijay Abraham I
From: Faiz Abbas 

Serdes lanes might be shared between multiple cores in some usecases
and its not possible to lock PLLs for both the lanes independently
by the two cores. This requires a bootloader to configure both the
lanes at early boot time.

To handle this case, skip all configuration if any of the lanes has
already been enabled.

Signed-off-by: Faiz Abbas 
Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/phy/ti/phy-j721e-wiz.c | 21 -
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c
index 659597645201..95905e5c4f3d 100644
--- a/drivers/phy/ti/phy-j721e-wiz.c
+++ b/drivers/phy/ti/phy-j721e-wiz.c
@@ -1132,13 +1132,14 @@ static int wiz_probe(struct platform_device *pdev)
struct device *dev = >dev;
struct device_node *node = dev->of_node;
struct platform_device *serdes_pdev;
+   bool already_configured = false;
struct device_node *child_node;
struct regmap *regmap;
struct resource res;
void __iomem *base;
struct wiz *wiz;
+   int ret, val, i;
u32 num_lanes;
-   int ret;
 
wiz = devm_kzalloc(dev, sizeof(*wiz), GFP_KERNEL);
if (!wiz)
@@ -1266,10 +1267,20 @@ static int wiz_probe(struct platform_device *pdev)
goto err_get_sync;
}
 
-   ret = wiz_init(wiz);
-   if (ret) {
-   dev_err(dev, "WIZ initialization failed\n");
-   goto err_wiz_init;
+   for (i = 0; i < wiz->num_lanes; i++) {
+   regmap_field_read(wiz->p_enable[i], );
+   if (val & (P_ENABLE | P_ENABLE_FORCE)) {
+   already_configured = true;
+   break;
+   }
+   }
+
+   if (!already_configured) {
+   ret = wiz_init(wiz);
+   if (ret) {
+   dev_err(dev, "WIZ initialization failed\n");
+   goto err_wiz_init;
+   }
}
 
serdes_pdev = of_platform_device_create(child_node, NULL, dev);
-- 
2.17.1



[PATCH v2 0/5] j721e-wiz/cadence-torrent: Support to skip SERDES configuration

2021-03-30 Thread Kishon Vijay Abraham I
Add support to skip SERDES configuration if it's already configured in
bootloader.

The wiz part was initially sent in [1] but that was sent more in the
context of Sierra but this is in context of Torrent. The Sierra part
would be sent later.

v1 of the patch series can be found at [2].

Changes from v1:
1) Added a patch to wait for PIPE clock to be stable
2) Added reviewed by from Swapnil

[1] -> http://lore.kernel.org/r/20201103035556.21260-1-kis...@ti.com
[2] -> http://lore.kernel.org/r/20210310155445.534-1-kis...@ti.com

Faiz Abbas (1):
  phy: ti: j721e-wiz: Do not configure wiz if its already configured

Kishon Vijay Abraham I (4):
  phy: cadence-torrent: Group reset APIs and clock APIs
  phy: cadence-torrent: Do not configure SERDES if it's already
configured
  phy: cadence-torrent: Explicitly request exclusive reset control
  phy: cadence-torrent: Add delay for PIPE clock to be stable

 drivers/phy/cadence/phy-cadence-torrent.c | 115 +++---
 drivers/phy/ti/phy-j721e-wiz.c|  21 +++-
 2 files changed, 95 insertions(+), 41 deletions(-)

-- 
2.17.1



Re: [PATCH 3/4] phy: cadence-torrent: Do not configure SERDES if it's already configured

2021-03-30 Thread Kishon Vijay Abraham I
Hi Swapnil,

On 18/03/21 3:25 pm, Swapnil Kashinath Jakhade wrote:
> 
> 
>> -Original Message-----
>> From: Kishon Vijay Abraham I 
>> Sent: Wednesday, March 10, 2021 9:25 PM
>> To: Kishon Vijay Abraham I ; Vinod Koul
>> ; Rob Herring ; Philipp Zabel
>> ; Swapnil Kashinath Jakhade
>> 
>> Cc: linux-kernel@vger.kernel.org; devicet...@vger.kernel.org; Lokesh Vutla
>> ; linux-...@lists.infradead.org
>> Subject: [PATCH 3/4] phy: cadence-torrent: Do not configure SERDES if it's
>> already configured
>>
>> EXTERNAL MAIL
>>
>>
>> Do not configure torrent SERDES if it's already configured.
>>
>> Signed-off-by: Kishon Vijay Abraham I 
>> ---
>>  drivers/phy/cadence/phy-cadence-torrent.c | 32 ---
>>  1 file changed, 22 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/phy/cadence/phy-cadence-torrent.c
>> b/drivers/phy/cadence/phy-cadence-torrent.c
>> index ab51c4bf7b30..5ee1657f5a1c 100644
>> --- a/drivers/phy/cadence/phy-cadence-torrent.c
>> +++ b/drivers/phy/cadence/phy-cadence-torrent.c
>> @@ -371,6 +371,10 @@ static const struct phy_ops cdns_torrent_phy_ops =
>> {
>>  .owner  = THIS_MODULE,
>>  };
>>
>> +static const struct phy_ops noop_ops = {
>> +.owner  = THIS_MODULE,
>> +};
>> +
>>  struct cdns_reg_pairs {
>>  u32 val;
>>  u32 off;
>> @@ -2306,6 +2310,7 @@ static int cdns_torrent_phy_probe(struct
>> platform_device *pdev)
>>  struct device_node *child;
>>  int ret, subnodes, node = 0, i;
>>  u32 total_num_lanes = 0;
>> +int already_configured;
>>  u8 init_dp_regmap = 0;
>>  u32 phy_type;
>>
>> @@ -2344,16 +2349,20 @@ static int cdns_torrent_phy_probe(struct
>> platform_device *pdev)
>>  if (ret)
>>  return ret;
>>
>> -ret = cdns_torrent_reset(cdns_phy);
>> -if (ret)
>> -goto clk_cleanup;
>> +regmap_field_read(cdns_phy->phy_pma_cmn_ctrl_1,
>> _configured);
>>
>> -ret = cdns_torrent_clk(cdns_phy);
>> -if (ret)
>> -goto clk_cleanup;
>> +if (!already_configured) {
>> +ret = cdns_torrent_reset(cdns_phy);
>> +if (ret)
>> +goto clk_cleanup;
>> +
>> +ret = cdns_torrent_clk(cdns_phy);
>> +if (ret)
>> +goto clk_cleanup;
>>
> Should if (!already_configured) be checked while calling 
> clk_disable_unprepare()?

Both clk_unprepare() and clk_disable() checks for passed clk for ERR or
NULL. So don't think it's necessary to have !already_configured check.
> Otherwise,
> Reviewed-by: Swapnil Jakhade 

Thanks
Kishon

> 
> Thanks & regards,
> Swapnil
> 
>> -/* Enable APB */
>> -reset_control_deassert(cdns_phy->apb_rst);
>> +/* Enable APB */
>> +reset_control_deassert(cdns_phy->apb_rst);
>> +}
>>
>>  for_each_available_child_of_node(dev->of_node, child) {
>>  struct phy *gphy;
>> @@ -2423,7 +2432,10 @@ static int cdns_torrent_phy_probe(struct
>> platform_device *pdev)
>>  of_property_read_u32(child, "cdns,ssc-mode",
>>   _phy->phys[node].ssc_mode);
>>
>> -gphy = devm_phy_create(dev, child,
>> _torrent_phy_ops);
>> +if (!already_configured)
>> +gphy = devm_phy_create(dev, child,
>> _torrent_phy_ops);
>> +else
>> +gphy = devm_phy_create(dev, child, _ops);
>>  if (IS_ERR(gphy)) {
>>  ret = PTR_ERR(gphy);
>>  goto put_child;
>> @@ -2507,7 +2519,7 @@ static int cdns_torrent_phy_probe(struct
>> platform_device *pdev)
>>  goto put_lnk_rst;
>>  }
>>
>> -if (cdns_phy->nsubnodes > 1) {
>> +if (cdns_phy->nsubnodes > 1 && !already_configured) {
>>  ret = cdns_torrent_phy_configure_multilink(cdns_phy);
>>  if (ret)
>>  goto put_lnk_rst;
>> --
>> 2.17.1
> 


Re: [PATCH 1/6] dt-bindings: PCI: ti,am65: Add PCIe host mode dt-bindings for TI's AM65 SoC

2021-03-30 Thread Kishon Vijay Abraham I
Hi Rob,

On 26/03/21 5:08 am, Rob Herring wrote:
> On Thu, Mar 25, 2021 at 02:30:21PM +0530, Kishon Vijay Abraham I wrote:
>> Add PCIe host mode dt-bindings for TI's AM65 SoC.
>>
>> Signed-off-by: Kishon Vijay Abraham I 
>> ---
>>  .../bindings/pci/ti,am65-pci-host.yaml| 111 ++
>>  1 file changed, 111 insertions(+)
>>  create mode 100644 
>> Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml
>>
>> diff --git a/Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml 
>> b/Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml
>> new file mode 100644
>> index ..b77e492886fa
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml
>> @@ -0,0 +1,111 @@
>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>> +# Copyright (C) 2021 Texas Instruments Incorporated - http://www.ti.com/
>> +%YAML 1.2
>> +---
>> +$id: "http://devicetree.org/schemas/pci/ti,am65-pci-host.yaml#;
>> +$schema: "http://devicetree.org/meta-schemas/core.yaml#;
>> +
>> +title: TI AM65 PCI Host
>> +
>> +maintainers:
>> +  - Kishon Vijay Abraham I 
>> +
>> +allOf:
>> +  - $ref: /schemas/pci/pci-bus.yaml#
>> +
>> +properties:
>> +  compatible:
>> +enum:
>> +  - ti,am654-pcie-rc
>> +
>> +  reg:
>> +maxItems: 4
>> +
>> +  reg-names:
>> +items:
>> +  - const: app
>> +  - const: dbics
> 
> Please use 'dbi' like everyone else if this isn't shared with the other 
> TI DW PCI bindings.

I'm just converting existing binding in pci-keystone.txt to yaml.
Documentation/devicetree/bindings/pci/pci-keystone.txt

Device tree for AM65 is also already in the upstream kernel.

I can try to remove the am65 specific part from pci-keystone.txt
> 
>> +  - const: config
>> +  - const: atu
>> +
>> +  power-domains:
>> +maxItems: 1
>> +
>> +  ti,syscon-pcie-id:
>> +description: Phandle to the SYSCON entry required for getting PCIe 
>> device/vendor ID
>> +$ref: /schemas/types.yaml#/definitions/phandle
>> +
>> +  ti,syscon-pcie-mode:
>> +description: Phandle to the SYSCON entry required for configuring PCIe 
>> in RC or EP mode.
>> +$ref: /schemas/types.yaml#/definitions/phandle
>> +
>> +  msi-map: true
>> +
>> +  dma-coherent: true
>> +
>> +patternProperties:
>> +  "interrupt-controller":
> 
> Don't need quotes.

sure, will fix it.
> 
>> +type: object
>> +description: interrupt controller to handle legacy interrupts.
>> +
>> +required:
>> +  - compatible
>> +  - reg
>> +  - reg-names
>> +  - max-link-speed
>> +  - num-lanes
>> +  - power-domains
>> +  - ti,syscon-pcie-id
>> +  - ti,syscon-pcie-mode
>> +  - msi-map
>> +  - ranges
>> +  - reset-gpios
>> +  - phys
>> +  - phy-names
>> +  - dma-coherent
> 
> 'interrupt-controller' node is optional?

yeah, upstream DT doesn't have interrupt-controller. It's added as part
of this series.

Thanks
Kishon
> 
>> +
>> +unevaluatedProperties: false
>> +
>> +examples:
>> +  - |
>> +#include 
>> +#include 
>> +
>> +bus {
>> +#address-cells = <2>;
>> +#size-cells = <2>;
>> +
>> +pcie0_rc: pcie@550 {
>> +compatible = "ti,am654-pcie-rc";
>> +reg =  <0x0 0x550 0x0 0x1000>,
>> +   <0x0 0x5501000 0x0 0x1000>,
>> +   <0x0 0x1000 0x0 0x2000>,
>> +   <0x0 0x5506000 0x0 0x1000>;
>> +reg-names = "app", "dbics", "config", "atu";
>> +power-domains = <_pds 120 TI_SCI_PD_EXCLUSIVE>;
>> +#address-cells = <3>;
>> +#size-cells = <2>;
>> +ranges = <0x8100 0 0  0x0 0x1002 0 
>> 0x0001>,
>> + <0x8200 0 0x1003 0x0 0x1003 0 
>> 0x07FD>;
>> +ti,syscon-pcie-id = <_devid>;
>> +ti,syscon-pcie-mode = <_mode>;
>> +bus-range = <0x0 0xff>;
>> +num-viewport = <16>;
>> +max-link-speed = <2>;
>> +dma-coherent;
>> +interrupts = ;
>> +msi-map = <0x0 _its 0x0 0x1>;
>> +#interrupt-cells = <1>;
>> +interrupt-map-mask = <0 0 0 7>;
>> +interrupt-map = <0 0 0 1 _intc 0>, /* INT A */
>> +<0 0 0 2 _intc 0>, /* INT B */
>> +<0 0 0 3 _intc 0>, /* INT C */
>> +<0 0 0 4 _intc 0>; /* INT D */
>> +
>> +pcie0_intc: interrupt-controller {
>> +interrupt-controller;
>> +#interrupt-cells = <1>;
>> +interrupt-parent = <>;
>> +interrupts = ;
>> +};
>> +};
>> -- 
>> 2.17.1
>>


Re: [PATCH v9 3/3] arm64: dts: ti: k3-j7200: Add support for higher speed modes and update delay select values for MMCSD subsystems

2021-03-26 Thread Kishon Vijay Abraham I
Hi,

On 26/03/21 12:11 pm, Aswath Govindraju wrote:
> The following speed modes are now supported in J7200 SoC,
> - HS200 and HS400 modes at 1.8 V card voltage, in MMCSD0 subsystem [1].
> - UHS-I speed modes in MMCSD1 subsystem [1].
> 
> Add support for UHS-I modes by adding voltage regulator device tree nodes
> and corresponding pinmux details, to power cycle and voltage switch cards.
> Set respective tags in sdhci0 and remove no-1-8-v tag from sdhci1
> device tree nodes.
> 
> Also update the delay values for various speed modes supported, based on
> the revised january 2021 J7200 datasheet[2].
> 
> [1] - section 12.3.6.1.1 MMCSD Features, in
>   https://www.ti.com/lit/ug/spruiu1a/spruiu1a.pdf,
>   (SPRUIU1A – JULY 2020 – REVISED JANUARY 2021)
> 
> [2] - https://www.ti.com/lit/ds/symlink/dra821u.pdf,
>   (SPRSP57B – APRIL 2020 – REVISED JANUARY 2021)
> 
> Signed-off-by: Aswath Govindraju 
> Reviewed-by: Kishon Vijay Abraham I 

Thanks! Patch looks good to me.

Regards
Kishon

> ---
>  .../dts/ti/k3-j7200-common-proc-board.dts | 78 +++
>  arch/arm64/boot/dts/ti/k3-j7200-main.dtsi | 14 +++-
>  2 files changed, 90 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts 
> b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts
> index b493f939b09a..bedd01b7a32c 100644
> --- a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts
> +++ b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts
> @@ -16,6 +16,65 @@
>   stdout-path = "serial2:115200n8";
>   bootargs = "console=ttyS2,115200n8 
> earlycon=ns16550a,mmio32,0x0280";
>   };
> +
> + evm_12v0: fixedregulator-evm12v0 {
> + /* main supply */
> + compatible = "regulator-fixed";
> + regulator-name = "evm_12v0";
> + regulator-min-microvolt = <1200>;
> + regulator-max-microvolt = <1200>;
> + regulator-always-on;
> + regulator-boot-on;
> + };
> +
> + vsys_3v3: fixedregulator-vsys3v3 {
> + /* Output of LM5140 */
> + compatible = "regulator-fixed";
> + regulator-name = "vsys_3v3";
> + regulator-min-microvolt = <330>;
> + regulator-max-microvolt = <330>;
> + vin-supply = <_12v0>;
> + regulator-always-on;
> + regulator-boot-on;
> + };
> +
> + vsys_5v0: fixedregulator-vsys5v0 {
> + /* Output of LM5140 */
> + compatible = "regulator-fixed";
> + regulator-name = "vsys_5v0";
> + regulator-min-microvolt = <500>;
> + regulator-max-microvolt = <500>;
> + vin-supply = <_12v0>;
> + regulator-always-on;
> + regulator-boot-on;
> + };
> +
> + vdd_mmc1: fixedregulator-sd {
> + /* Output of TPS22918 */
> + compatible = "regulator-fixed";
> + regulator-name = "vdd_mmc1";
> + regulator-min-microvolt = <330>;
> + regulator-max-microvolt = <330>;
> + regulator-boot-on;
> + enable-active-high;
> + vin-supply = <_3v3>;
> + gpio = < 2 GPIO_ACTIVE_HIGH>;
> + };
> +
> + vdd_sd_dv: gpio-regulator-TLV71033 {
> + /* Output of TLV71033 */
> + compatible = "regulator-gpio";
> + regulator-name = "tlv71033";
> + pinctrl-names = "default";
> + pinctrl-0 = <_sd_dv_pins_default>;
> + regulator-min-microvolt = <180>;
> + regulator-max-microvolt = <330>;
> + regulator-boot-on;
> + vin-supply = <_5v0>;
> + gpios = <_gpio0 55 GPIO_ACTIVE_HIGH>;
> + states = <180 0x0>,
> +  <330 0x1>;
> + };
>  };
>  
>  _pmx0 {
> @@ -45,6 +104,13 @@
>  };
>  
>  _pmx0 {
> + main_i2c0_pins_default: main-i2c0-pins-default {
> + pinctrl-single,pins = <
> + J721E_IOPAD(0xd4, PIN_INPUT_PULLUP, 0) /* (V3) I2C0_SCL 
> */
> + J721E_IOPAD(0xd8, PIN_INPUT_PULLUP, 0) /* (W2) I2C0_SDA 
> */
> + >;
> + };
> +
>   main_i2c1_pins_default: main-i2c1-pins-default {
>   pinctrl-single,pins = <
>   J721E_IOPAD(0xdc,

Re: [PATCH v8 3/3] arm64: dts: ti: k3-j7200: Add support for higher speed modes and update delay select values for MMCSD subsystems

2021-03-25 Thread Kishon Vijay Abraham I
Hi Aswath,

On 24/03/21 12:07 pm, Aswath Govindraju wrote:
> The following speed modes are now supported in J7200 SoC,
> - HS200 and HS400 modes at 1.8 V card voltage, in MMCSD0 subsystem [1].
> - UHS-I speed modes in MMCSD1 subsystem [1].
> 
> Add support for UHS-I modes by adding voltage regulator device tree nodes
> and corresponding pinmux details, to power cycle and voltage switch cards.
> Set respective tags in sdhci0 and remove no-1-8-v tag from sdhci1
> device tree nodes.
> 
> Also update the delay values for various speed modes supported, based on
> the revised january 2021 J7200 datasheet[2].
> 
> [1] - section 12.3.6.1.1 MMCSD Features, in
>   https://www.ti.com/lit/ug/spruiu1a/spruiu1a.pdf,
>   (SPRUIU1A – JULY 2020 – REVISED JANUARY 2021)
> 
> [2] - https://www.ti.com/lit/ds/symlink/dra821u.pdf,
>   (SPRSP57B – APRIL 2020 – REVISED JANUARY 2021)
minor comments below.. once you fix them, please add

Reviewed-by: Kishon Vijay Abraham I 
> 
> Signed-off-by: Aswath Govindraju 
> ---
>  .../dts/ti/k3-j7200-common-proc-board.dts | 78 +++
>  arch/arm64/boot/dts/ti/k3-j7200-main.dtsi | 14 +++-
>  2 files changed, 90 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts 
> b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts
> index b493f939b09a..a069787e1783 100644
> --- a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts
> +++ b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts
> @@ -16,6 +16,65 @@
>   stdout-path = "serial2:115200n8";
>   bootargs = "console=ttyS2,115200n8 
> earlycon=ns16550a,mmio32,0x0280";
>   };
> +
> + evm_12v0: fixedregulator-evm12v0 {
> + /* main supply */
> + compatible = "regulator-fixed";
> + regulator-name = "evm_12v0";
> + regulator-min-microvolt = <1200>;
> + regulator-max-microvolt = <1200>;
> + regulator-always-on;
> + regulator-boot-on;
> + };
> +
> + vsys_3v3: fixedregulator-vsys3v3 {
> + /* Output of LMS140 */

%s/LMS140/LM5140
> + compatible = "regulator-fixed";
> + regulator-name = "vsys_3v3";
> + regulator-min-microvolt = <330>;
> + regulator-max-microvolt = <330>;
> + vin-supply = <_12v0>;
> + regulator-always-on;
> + regulator-boot-on;
> + };
> +
> + vsys_5v0: fixedregulator-vsys5v0 {
> + /* Output of LM5140 */
> + compatible = "regulator-fixed";
> + regulator-name = "vsys_5v0";
> + regulator-min-microvolt = <500>;
> + regulator-max-microvolt = <500>;
> + vin-supply = <_12v0>;
> + regulator-always-on;
> + regulator-boot-on;
> + };
> +
> + vdd_mmc1: fixedregulator-sd {
> + /* Output of TPS22918  */
> + compatible = "regulator-fixed";
> + regulator-name = "vdd_mmc1";
> + regulator-min-microvolt = <330>;
> + regulator-max-microvolt = <330>;
> + regulator-boot-on;
> + enable-active-high;
> + vin-supply = <_3v3>;
> + gpio = < 2 GPIO_ACTIVE_HIGH>;
> + };
> +
> + vdd_sd_dv: gpio-regulator-vdd-sd-dv {
> + /* Output of TLV71033 */

Would have preferred to keep this similar to j721e.
gpio-regulator-TLV71033 is used in j721e
> + compatible = "regulator-gpio";
> + regulator-name = "vdd_sd_dv";

same comment here..
> + pinctrl-names = "default";
> + pinctrl-0 = <_sd_dv_pins_default>;
> + regulator-min-microvolt = <180>;
> + regulator-max-microvolt = <330>;
> + regulator-boot-on;
> + vin-supply = <_5v0>;
> + gpios = <_gpio0 55 GPIO_ACTIVE_HIGH>;
> + states = <180 0x0>,
> +  <330 0x1>;
> + };
>  };
>  
>  _pmx0 {
> @@ -45,6 +104,13 @@
>  };
>  
>  _pmx0 {
> + main_i2c0_pins_default: main-i2c0-pins-default {
> + pinctrl-single,pins = <
> + J721E_IOPAD(0xd4, PIN_INPUT_PULLUP, 0) /* (V3) I2C0_SCL 
> */
> + J721E_IOPAD(0xd8, PIN_INPUT_PULLUP, 0) /* (W2) I2C0_SDA 
> */
> + >;
> + };
> +
>   main_

[PATCH 4/4] PCI: j721e: Add PCIe support for AM64

2021-03-25 Thread Kishon Vijay Abraham I
AM64 has the same PCIe IP as in J7200 (legacy interrupt handling is
same as J7200 instead of J721E). Add support for "ti,am64-pcie-host"
compatible that is specific to AM64.

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/pci/controller/cadence/pci-j721e.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/pci/controller/cadence/pci-j721e.c 
b/drivers/pci/controller/cadence/pci-j721e.c
index f175f116abf6..38895a5f4b68 100644
--- a/drivers/pci/controller/cadence/pci-j721e.c
+++ b/drivers/pci/controller/cadence/pci-j721e.c
@@ -467,6 +467,10 @@ static const struct of_device_id of_j721e_pcie_match[] = {
.compatible = "ti,j7200-pcie-host",
.data = _pcie_rc_data,
},
+   {
+   .compatible = "ti,am64-pcie-host",
+   .data = _pcie_rc_data,
+   },
{},
 };
 
-- 
2.17.1



[PATCH 3/4] PCI: j721e: Add PCIe support for j7200

2021-03-25 Thread Kishon Vijay Abraham I
J7200 has the same PCIe IP as in J721E with minor changes in the
wrapper. Add PCIe support for j7200 accounting for the wrapper
changes in pci-j721e.c
Changes from J721E:
 *) Allows byte access of bridge configuration space registers
 *) Changes in legacy interrupt register map

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/pci/controller/cadence/pci-j721e.c | 111 ++---
 1 file changed, 99 insertions(+), 12 deletions(-)

diff --git a/drivers/pci/controller/cadence/pci-j721e.c 
b/drivers/pci/controller/cadence/pci-j721e.c
index 17db86a51ca8..f175f116abf6 100644
--- a/drivers/pci/controller/cadence/pci-j721e.c
+++ b/drivers/pci/controller/cadence/pci-j721e.c
@@ -27,6 +27,7 @@
 #define STATUS_REG_SYS_2   0x508
 #define STATUS_CLR_REG_SYS_2   0x708
 #define LINK_DOWN  BIT(1)
+#define J7200_LINK_DOWNBIT(10)
 
 #define EOI_REG0x10
 
@@ -35,6 +36,10 @@
 #define STATUS_CLR_REG_SYS_0   0x700
 #define INTx_EN(num)   (1 << (num))
 
+#define ENABLE_REG_SYS_1   0x104
+#define STATUS_REG_SYS_1   0x504
+#define SYS1_INTx_EN(num)  (1 << (22 + (num)))
+
 #define J721E_PCIE_USER_CMD_STATUS 0x4
 #define LINK_TRAINING_ENABLE   BIT(0)
 
@@ -48,6 +53,14 @@ enum link_status {
LINK_UP_DL_COMPLETED,
 };
 
+#define USER_EOI_REG   0xC8
+enum eoi_reg {
+   EOI_DOWNSTREAM_INTERRUPT,
+   EOI_FLR_INTERRUPT,
+   EOI_LEGACY_INTERRUPT,
+   EOI_POWER_STATE_INTERRUPT,
+};
+
 #define J721E_MODE_RC  BIT(7)
 #define LANE_COUNT_MASKBIT(8)
 #define LANE_COUNT(n)  ((n) << 8)
@@ -65,6 +78,8 @@ struct j721e_pcie {
void __iomem*user_cfg_base;
void __iomem*intd_cfg_base;
struct irq_domain   *legacy_irq_domain;
+   boolis_intc_v1;
+   u32 link_irq_reg_field;
 };
 
 enum j721e_pcie_mode {
@@ -75,6 +90,9 @@ enum j721e_pcie_mode {
 struct j721e_pcie_data {
enum j721e_pcie_modemode;
bool quirk_retrain_flag;
+   boolis_intc_v1;
+   boolbyte_access_allowed;
+   const struct cdns_pcie_ops *ops;
 };
 
 static inline u32 j721e_pcie_user_readl(struct j721e_pcie *pcie, u32 offset)
@@ -106,12 +124,12 @@ static irqreturn_t j721e_pcie_link_irq_handler(int irq, 
void *priv)
u32 reg;
 
reg = j721e_pcie_intd_readl(pcie, STATUS_REG_SYS_2);
-   if (!(reg & LINK_DOWN))
+   if (!(reg & pcie->link_irq_reg_field))
return IRQ_NONE;
 
dev_err(dev, "LINK DOWN!\n");
 
-   j721e_pcie_intd_writel(pcie, STATUS_CLR_REG_SYS_2, LINK_DOWN);
+   j721e_pcie_intd_writel(pcie, STATUS_CLR_REG_SYS_2, 
pcie->link_irq_reg_field);
return IRQ_HANDLED;
 }
 
@@ -119,12 +137,40 @@ static void j721e_pcie_config_link_irq(struct j721e_pcie 
*pcie)
 {
u32 reg;
 
+   pcie->link_irq_reg_field = J7200_LINK_DOWN;
+   if (pcie->is_intc_v1)
+   pcie->link_irq_reg_field = LINK_DOWN;
+
reg = j721e_pcie_intd_readl(pcie, ENABLE_REG_SYS_2);
-   reg |= LINK_DOWN;
+   reg |= pcie->link_irq_reg_field;
j721e_pcie_intd_writel(pcie, ENABLE_REG_SYS_2, reg);
 }
 
 static void j721e_pcie_legacy_irq_handler(struct irq_desc *desc)
+{
+   struct j721e_pcie *pcie = irq_desc_get_handler_data(desc);
+   struct irq_chip *chip = irq_desc_get_chip(desc);
+   int virq;
+   u32 reg;
+   int i;
+
+   chained_irq_enter(chip, desc);
+
+   for (i = 0; i < PCI_NUM_INTX; i++) {
+   reg = j721e_pcie_intd_readl(pcie, STATUS_REG_SYS_1);
+   if (!(reg & SYS1_INTx_EN(i)))
+   continue;
+
+   virq = irq_find_mapping(pcie->legacy_irq_domain, i);
+   generic_handle_irq(virq);
+   j721e_pcie_user_writel(pcie, USER_EOI_REG,
+  EOI_LEGACY_INTERRUPT);
+   }
+
+   chained_irq_exit(chip, desc);
+}
+
+static void j721e_pcie_v1_legacy_irq_handler(struct irq_desc *desc)
 {
int i;
u32 reg;
@@ -182,8 +228,14 @@ static int j721e_pcie_config_legacy_irq(struct j721e_pcie 
*pcie)
dev_err(dev, "Failed to parse and map legacy irq\n");
return -EINVAL;
}
-   irq_set_chained_handler_and_data(irq, j721e_pcie_legacy_irq_handler,
-pcie);
+
+   if (pcie->is_intc_v1) {
+   irq_set_chained_handler_and_data(irq, 
j721e_pcie_v1_legacy_irq_handler,
+pcie);
+   } else {
+   irq_set_chained_handler_and_data(irq, 
j721e_pcie_legacy_irq_handler,
+pcie);
+   }
 
legacy_irq_domain = irq_domain_add_linear(intc_node, PCI_NUM_INTX,
  

[PATCH 2/4] PCI: j721e: Add PCI legacy interrupt support for J721E

2021-03-25 Thread Kishon Vijay Abraham I
Add PCI legacy interrupt support for J721E. J721E has a single HW
interrupt line for all the four legacy interrupts INTA/INTB/INTC/INTD.
The HW interrupt line connected to GIC is a pulse interrupt whereas
the legacy interrupts by definition is level interrupt. In order to
provide level interrupt functionality to edge interrupt line, PCIe
in J721E has provided IRQ_EOI register. When the SW writes to IRQ_EOI
register after handling the interrupt, the IP checks the state of
legacy interrupt and re-triggers pulse interrupt invoking the handler
again.

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/pci/controller/cadence/pci-j721e.c | 91 ++
 1 file changed, 91 insertions(+)

diff --git a/drivers/pci/controller/cadence/pci-j721e.c 
b/drivers/pci/controller/cadence/pci-j721e.c
index 0382bb15c6f9..17db86a51ca8 100644
--- a/drivers/pci/controller/cadence/pci-j721e.c
+++ b/drivers/pci/controller/cadence/pci-j721e.c
@@ -28,6 +28,13 @@
 #define STATUS_CLR_REG_SYS_2   0x708
 #define LINK_DOWN  BIT(1)
 
+#define EOI_REG0x10
+
+#define ENABLE_REG_SYS_0   0x100
+#define STATUS_REG_SYS_0   0x500
+#define STATUS_CLR_REG_SYS_0   0x700
+#define INTx_EN(num)   (1 << (num))
+
 #define J721E_PCIE_USER_CMD_STATUS 0x4
 #define LINK_TRAINING_ENABLE   BIT(0)
 
@@ -57,6 +64,7 @@ struct j721e_pcie {
struct cdns_pcie*cdns_pcie;
void __iomem*user_cfg_base;
void __iomem*intd_cfg_base;
+   struct irq_domain   *legacy_irq_domain;
 };
 
 enum j721e_pcie_mode {
@@ -116,6 +124,85 @@ static void j721e_pcie_config_link_irq(struct j721e_pcie 
*pcie)
j721e_pcie_intd_writel(pcie, ENABLE_REG_SYS_2, reg);
 }
 
+static void j721e_pcie_legacy_irq_handler(struct irq_desc *desc)
+{
+   int i;
+   u32 reg;
+   int virq;
+   struct j721e_pcie *pcie = irq_desc_get_handler_data(desc);
+   struct irq_chip *chip = irq_desc_get_chip(desc);
+
+   chained_irq_enter(chip, desc);
+
+   for (i = 0; i < PCI_NUM_INTX; i++) {
+   reg = j721e_pcie_intd_readl(pcie, STATUS_REG_SYS_0);
+   if (!(reg & INTx_EN(i)))
+   continue;
+
+   virq = irq_find_mapping(pcie->legacy_irq_domain, 3 - i);
+   generic_handle_irq(virq);
+   j721e_pcie_intd_writel(pcie, STATUS_CLR_REG_SYS_0, INTx_EN(i));
+   j721e_pcie_intd_writel(pcie, EOI_REG, 3 - i);
+   }
+
+   chained_irq_exit(chip, desc);
+}
+
+static int j721e_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
+  irq_hw_number_t hwirq)
+{
+   irq_set_chip_and_handler(irq, _irq_chip, handle_simple_irq);
+   irq_set_chip_data(irq, domain->host_data);
+
+   return 0;
+}
+
+static const struct irq_domain_ops j721e_pcie_intx_domain_ops = {
+   .map = j721e_pcie_intx_map,
+};
+
+static int j721e_pcie_config_legacy_irq(struct j721e_pcie *pcie)
+{
+   struct device *dev = pcie->dev;
+   struct irq_domain *legacy_irq_domain;
+   struct device_node *node = dev->of_node;
+   struct device_node *intc_node;
+   int irq;
+   u32 reg;
+   int i;
+
+   intc_node = of_get_child_by_name(node, "interrupt-controller");
+   if (!intc_node) {
+   dev_WARN(dev, "legacy-interrupt-controller node is absent\n");
+   return -EINVAL;
+   }
+
+   irq = irq_of_parse_and_map(intc_node, 0);
+   if (!irq) {
+   dev_err(dev, "Failed to parse and map legacy irq\n");
+   return -EINVAL;
+   }
+   irq_set_chained_handler_and_data(irq, j721e_pcie_legacy_irq_handler,
+pcie);
+
+   legacy_irq_domain = irq_domain_add_linear(intc_node, PCI_NUM_INTX,
+ _pcie_intx_domain_ops,
+ NULL);
+   if (!legacy_irq_domain) {
+   dev_err(dev, "Failed to add irq domain for legacy irqs\n");
+   return -EINVAL;
+   }
+   pcie->legacy_irq_domain = legacy_irq_domain;
+
+   for (i = 0; i < PCI_NUM_INTX; i++) {
+   reg = j721e_pcie_intd_readl(pcie, ENABLE_REG_SYS_0);
+   reg |= INTx_EN(i);
+   j721e_pcie_intd_writel(pcie, ENABLE_REG_SYS_0, reg);
+   }
+
+   return 0;
+}
+
 static int j721e_pcie_start_link(struct cdns_pcie *cdns_pcie)
 {
struct j721e_pcie *pcie = dev_get_drvdata(cdns_pcie->dev);
@@ -385,6 +472,10 @@ static int j721e_pcie_probe(struct platform_device *pdev)
goto err_get_sync;
}
 
+   ret = j721e_pcie_config_legacy_irq(pcie);
+   if (ret < 0)
+   goto err_get_sync;
+
bridge = devm_pci_alloc_host_bridge(dev, sizeof(*rc));
if (!bridge) {
ret = -ENOMEM;
-- 
2.17.1



[PATCH 0/4] PCI: Add legacy interrupt support in pci-j721e

2021-03-25 Thread Kishon Vijay Abraham I
Patch series adds support for legacy interrupt in pci-j721e. There are
two HW implementations of legacy interrupt controller, one specific to
J721E and the other for J7200/AM64.

In both these implementations, the legacy interrupt is connect to pulse
interrupt of GIC and level to pulse is handled by configuring EOI
register.

Kishon Vijay Abraham I (4):
  dt-bindings: PCI: ti,j721e: Add bindings to specify legacy interrupts
  PCI: j721e: Add PCI legacy interrupt support for J721E
  PCI: j721e: Add PCIe support for j7200
  PCI: j721e: Add PCIe support for AM64

 .../bindings/pci/ti,j721e-pci-host.yaml   |  13 ++
 drivers/pci/controller/cadence/pci-j721e.c| 194 +-
 2 files changed, 201 insertions(+), 6 deletions(-)

-- 
2.17.1



[PATCH 1/4] dt-bindings: PCI: ti,j721e: Add bindings to specify legacy interrupts

2021-03-25 Thread Kishon Vijay Abraham I
Add bindings to specify interrupt controller for legacy interrupts.

Signed-off-by: Kishon Vijay Abraham I 
---
 .../devicetree/bindings/pci/ti,j721e-pci-host.yaml  | 13 +
 1 file changed, 13 insertions(+)

diff --git a/Documentation/devicetree/bindings/pci/ti,j721e-pci-host.yaml 
b/Documentation/devicetree/bindings/pci/ti,j721e-pci-host.yaml
index 05aeb1aa362a..3e70a8049eea 100644
--- a/Documentation/devicetree/bindings/pci/ti,j721e-pci-host.yaml
+++ b/Documentation/devicetree/bindings/pci/ti,j721e-pci-host.yaml
@@ -73,6 +73,11 @@ properties:
 
   msi-map: true
 
+patternProperties:
+  "interrupt-controller":
+type: object
+description: interrupt controller to handle legacy interrupts.
+
 required:
   - compatible
   - reg
@@ -130,5 +135,13 @@ examples:
 ranges = <0x0100 0x0 0x10001000  0x00 0x10001000  0x0 
0x001>,
  <0x0200 0x0 0x10011000  0x00 0x10011000  0x0 
0x7fef000>;
 dma-ranges = <0x0200 0x0 0x0 0x0 0x0 0x1 0x0>;
+
+
+pcie0_intc: interrupt-controller {
+interrupt-controller;
+#interrupt-cells = <1>;
+interrupt-parent = <>;
+interrupts = ;
+};
 };
 };
-- 
2.17.1



[PATCH 4/6] PCI: keystone: Convert to using hierarchy domain for legacy interrupts

2021-03-25 Thread Kishon Vijay Abraham I
K2G provides separate IRQ lines for each of the four legacy interrupts.
Model this using hierarchy domain instead of linear domain with chained
IRQ handler.

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/pci/controller/dwc/pci-keystone.c | 214 --
 1 file changed, 120 insertions(+), 94 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c 
b/drivers/pci/controller/dwc/pci-keystone.c
index 4de8c8e5e3f2..dfa9a7fcf9b7 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -69,6 +69,7 @@
 
 #define IRQ_STATUS(n)  (0x184 + ((n) << 4))
 #define IRQ_ENABLE_SET(n)  (0x188 + ((n) << 4))
+#define IRQ_ENABLE_CLR(n)  (0x18c + ((n) << 4))
 #define INTx_ENBIT(0)
 
 #define ERR_IRQ_STATUS 0x1c4
@@ -116,7 +117,6 @@ struct keystone_pcie {
struct dw_pcie  *pci;
/* PCI Device ID */
u32 device_id;
-   int legacy_host_irqs[PCI_NUM_INTX];
struct  device_node *legacy_intc_np;
 
int msi_host_irq;
@@ -125,7 +125,6 @@ struct keystone_pcie {
struct phy  **phy;
struct device_link  **link;
struct  device_node *msi_intc_np;
-   struct irq_domain   *legacy_irq_domain;
struct device_node  *np;
 
/* Application register space */
@@ -253,26 +252,6 @@ static int ks_pcie_msi_host_init(struct pcie_port *pp)
return dw_pcie_allocate_domains(pp);
 }
 
-static void ks_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie,
- int offset)
-{
-   struct dw_pcie *pci = ks_pcie->pci;
-   struct device *dev = pci->dev;
-   u32 pending;
-   int virq;
-
-   pending = ks_pcie_app_readl(ks_pcie, IRQ_STATUS(offset));
-
-   if (BIT(0) & pending) {
-   virq = irq_linear_revmap(ks_pcie->legacy_irq_domain, offset);
-   dev_dbg(dev, ": irq: irq_offset %d, virq %d\n", offset, virq);
-   generic_handle_irq(virq);
-   }
-
-   /* EOI the INTx interrupt */
-   ks_pcie_app_writel(ks_pcie, IRQ_EOI, offset);
-}
-
 static void ks_pcie_enable_error_irq(struct keystone_pcie *ks_pcie)
 {
ks_pcie_app_writel(ks_pcie, ERR_IRQ_ENABLE_SET, ERR_IRQ_ALL);
@@ -310,39 +289,120 @@ static irqreturn_t ks_pcie_handle_error_irq(struct 
keystone_pcie *ks_pcie)
return IRQ_HANDLED;
 }
 
-static void ks_pcie_ack_legacy_irq(struct irq_data *d)
+void ks_pcie_irq_eoi(struct irq_data *data)
 {
+   struct keystone_pcie *ks_pcie = irq_data_get_irq_chip_data(data);
+   irq_hw_number_t hwirq = data->hwirq;
+
+   ks_pcie_app_writel(ks_pcie, IRQ_EOI, hwirq);
+   irq_chip_eoi_parent(data);
 }
 
-static void ks_pcie_mask_legacy_irq(struct irq_data *d)
+void ks_pcie_irq_enable(struct irq_data *data)
 {
+   struct keystone_pcie *ks_pcie = irq_data_get_irq_chip_data(data);
+   irq_hw_number_t hwirq = data->hwirq;
+
+   ks_pcie_app_writel(ks_pcie, IRQ_ENABLE_SET(hwirq), INTx_EN);
+   irq_chip_enable_parent(data);
 }
 
-static void ks_pcie_unmask_legacy_irq(struct irq_data *d)
+void ks_pcie_irq_disable(struct irq_data *data)
 {
+   struct keystone_pcie *ks_pcie = irq_data_get_irq_chip_data(data);
+   irq_hw_number_t hwirq = data->hwirq;
+
+   ks_pcie_app_writel(ks_pcie, IRQ_ENABLE_CLR(hwirq), INTx_EN);
+   irq_chip_disable_parent(data);
 }
 
 static struct irq_chip ks_pcie_legacy_irq_chip = {
-   .name = "Keystone-PCI-Legacy-IRQ",
-   .irq_ack = ks_pcie_ack_legacy_irq,
-   .irq_mask = ks_pcie_mask_legacy_irq,
-   .irq_unmask = ks_pcie_unmask_legacy_irq,
+   .name   = "Keystone-PCI-Legacy-IRQ",
+   .irq_enable = ks_pcie_irq_enable,
+   .irq_disable= ks_pcie_irq_disable,
+   .irq_eoi= ks_pcie_irq_eoi,
+   .irq_mask   = irq_chip_mask_parent,
+   .irq_unmask = irq_chip_unmask_parent,
+   .irq_retrigger  = irq_chip_retrigger_hierarchy,
+   .irq_set_type   = irq_chip_set_type_parent,
+   .irq_set_affinity   = irq_chip_set_affinity_parent,
 };
 
-static int ks_pcie_init_legacy_irq_map(struct irq_domain *d,
-  unsigned int irq,
-  irq_hw_number_t hw_irq)
+static int ks_pcie_legacy_irq_domain_alloc(struct irq_domain *domain, unsigned 
int virq,
+  unsigned int nr_irqs, void *data)
 {
-   irq_set_chip_and_handler(irq, _pcie_legacy_irq_chip,
-handle_level_irq);
-   irq_set_chip_data(irq, d->host_data);
+   struct keystone_pcie *ks_pcie = domain->host_data;
+   struct device

[PATCH 6/6] PCI: keystone: Add workaround for Errata #i2037 (AM65x SR 1.0)

2021-03-25 Thread Kishon Vijay Abraham I
Errata #i2037 in AM65x/DRA80xM Processors Silicon Revision 1.0
(SPRZ452D–July 2018–Revised December 2019 [1]) mentions when an
inbound PCIe TLP spans more than two internal AXI 128-byte bursts,
the bus may corrupt the packet payload and the corrupt data may
cause associated applications or the processor to hang.

The workaround for Errata #i2037 is to limit the maximum read
request size and maximum payload size to 128 Bytes. Add workaround
for Errata #i2037 here. The errata and workaround is applicable
only to AM65x SR 1.0 and later versions of the silicon will have
this fixed.

[1] -> http://www.ti.com/lit/er/sprz452d/sprz452d.pdf

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/pci/controller/dwc/pci-keystone.c | 42 +++
 1 file changed, 42 insertions(+)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c 
b/drivers/pci/controller/dwc/pci-keystone.c
index 84a25207d0d3..80b6e874199d 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -35,6 +35,11 @@
 #define PCIE_DEVICEID_SHIFT16
 
 /* Application registers */
+#define PID0x000
+#define RTLGENMASK(15, 11)
+#define RTL_SHIFT  11
+#define AM6_PCI_PG1_RTL_VER0x15
+
 #define CMD_STATUS 0x004
 #define LTSSM_EN_VAL   BIT(0)
 #define OB_XLAT_EN_VAL BIT(1)
@@ -106,6 +111,8 @@
 
 #define to_keystone_pcie(x)dev_get_drvdata((x)->dev)
 
+#define PCI_DEVICE_ID_TI_AM654X0xb00c
+
 struct ks_pcie_of_data {
enum dw_pcie_device_mode mode;
const struct dw_pcie_host_ops *host_ops;
@@ -619,7 +626,11 @@ static int ks_pcie_start_link(struct dw_pcie *pci)
 static void ks_pcie_quirk(struct pci_dev *dev)
 {
struct pci_bus *bus = dev->bus;
+   struct keystone_pcie *ks_pcie;
+   struct device *bridge_dev;
struct pci_dev *bridge;
+   u32 val;
+
static const struct pci_device_id rc_pci_devids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_TI, PCIE_RC_K2HK),
 .class = PCI_CLASS_BRIDGE_PCI << 8, .class_mask = ~0, },
@@ -631,6 +642,11 @@ static void ks_pcie_quirk(struct pci_dev *dev)
 .class = PCI_CLASS_BRIDGE_PCI << 8, .class_mask = ~0, },
{ 0, },
};
+   static const struct pci_device_id am6_pci_devids[] = {
+   { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_AM654X),
+.class = PCI_CLASS_BRIDGE_PCI << 8, .class_mask = ~0, },
+   { 0, },
+   };
 
if (pci_is_root_bus(bus))
bridge = dev;
@@ -656,6 +672,32 @@ static void ks_pcie_quirk(struct pci_dev *dev)
pcie_set_readrq(dev, 256);
}
}
+
+   /*
+* Memory transactions fail with PCI controller in AM654 PG1.0
+* when MRRS is set to more than 128 Bytes. Force the MRRS to
+* 128 Bytes in all downstream devices.
+*/
+   if (pci_match_id(am6_pci_devids, bridge)) {
+   bridge_dev = pci_get_host_bridge_device(dev);
+   if (!bridge_dev && !bridge_dev->parent)
+   return;
+
+   ks_pcie = dev_get_drvdata(bridge_dev->parent);
+   if (!ks_pcie)
+   return;
+
+   val = ks_pcie_app_readl(ks_pcie, PID);
+   val &= RTL;
+   val >>= RTL_SHIFT;
+   if (val != AM6_PCI_PG1_RTL_VER)
+   return;
+
+   if (pcie_get_readrq(dev) > 128) {
+   dev_info(>dev, "limiting MRRS to 128\n");
+   pcie_set_readrq(dev, 128);
+   }
+   }
 }
 DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, ks_pcie_quirk);
 
-- 
2.17.1



[PATCH 5/6] PCI: keystone: Add PCI legacy interrupt support for AM654

2021-03-25 Thread Kishon Vijay Abraham I
Add PCI legacy interrupt support for AM654. AM654 has a single HW
interrupt line for all the four legacy interrupts INTA/INTB/INTC/INTD.
The HW interrupt line connected to GIC is a pulse interrupt whereas
the legacy interrupts by definition is level interrupt. In order to
provide level interrupt functionality to edge interrupt line, PCIe
in AM654 has provided IRQ_EOI register. When the SW writes to IRQ_EOI
register after handling the interrupt, the IP checks the state of
legacy interrupt and re-triggers pulse interrupt invoking the handler
again.

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/pci/controller/dwc/pci-keystone.c | 87 +--
 1 file changed, 82 insertions(+), 5 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c 
b/drivers/pci/controller/dwc/pci-keystone.c
index dfa9a7fcf9b7..84a25207d0d3 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -118,6 +118,7 @@ struct keystone_pcie {
/* PCI Device ID */
u32 device_id;
struct  device_node *legacy_intc_np;
+   struct irq_domain   *legacy_irq_domain;
 
int msi_host_irq;
int num_lanes;
@@ -289,6 +290,29 @@ static irqreturn_t ks_pcie_handle_error_irq(struct 
keystone_pcie *ks_pcie)
return IRQ_HANDLED;
 }
 
+static void ks_pcie_am654_legacy_irq_handler(struct irq_desc *desc)
+{
+   struct keystone_pcie *ks_pcie = irq_desc_get_handler_data(desc);
+   struct irq_chip *chip = irq_desc_get_chip(desc);
+   int virq, i;
+   u32 reg;
+
+   chained_irq_enter(chip, desc);
+
+   for (i = 0; i < PCI_NUM_INTX; i++) {
+   reg = ks_pcie_app_readl(ks_pcie, IRQ_STATUS(i));
+   if (!(reg & INTx_EN))
+   continue;
+
+   virq = irq_linear_revmap(ks_pcie->legacy_irq_domain, i);
+   generic_handle_irq(virq);
+   ks_pcie_app_writel(ks_pcie, IRQ_STATUS(i), INTx_EN);
+   ks_pcie_app_writel(ks_pcie, IRQ_EOI, i);
+   }
+
+   chained_irq_exit(chip, desc);
+}
+
 void ks_pcie_irq_eoi(struct irq_data *data)
 {
struct keystone_pcie *ks_pcie = irq_data_get_irq_chip_data(data);
@@ -728,6 +752,54 @@ static int ks_pcie_config_msi_irq(struct keystone_pcie 
*ks_pcie)
return ret;
 }
 
+static int ks_pcie_am654_intx_map(struct irq_domain *domain, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+   irq_set_chip_and_handler(irq, _irq_chip, handle_simple_irq);
+   irq_set_chip_data(irq, domain->host_data);
+
+   return 0;
+}
+
+static const struct irq_domain_ops ks_pcie_am654_irq_domain_ops = {
+   .map = ks_pcie_am654_intx_map,
+};
+
+static int ks_pcie_am654_config_legacy_irq(struct keystone_pcie *ks_pcie)
+{
+   struct device *dev = ks_pcie->pci->dev;
+   struct irq_domain *legacy_irq_domain;
+   struct device_node *np = ks_pcie->np;
+   struct device_node *intc_np;
+   int ret = 0;
+   int irq;
+   int i;
+
+   intc_np = of_get_child_by_name(np, "interrupt-controller");
+   if (!intc_np) {
+   dev_warn(dev, "legacy interrupt-controller node is absent\n");
+   return -EINVAL;
+   }
+
+   irq = irq_of_parse_and_map(intc_np, 0);
+   if (!irq)
+   return -EINVAL;
+
+   irq_set_chained_handler_and_data(irq, ks_pcie_am654_legacy_irq_handler, 
ks_pcie);
+   legacy_irq_domain = irq_domain_add_linear(intc_np, PCI_NUM_INTX,
+ 
_pcie_am654_irq_domain_ops, ks_pcie);
+   if (!legacy_irq_domain) {
+   dev_err(dev, "Failed to add irq domain for legacy irqs\n");
+   return -EINVAL;
+   }
+   ks_pcie->legacy_irq_domain = legacy_irq_domain;
+
+   for (i = 0; i < PCI_NUM_INTX; i++)
+   ks_pcie_app_writel(ks_pcie, IRQ_ENABLE_SET(i), INTx_EN);
+
+   return ret;
+}
+
 static int ks_pcie_config_legacy_irq(struct keystone_pcie *ks_pcie)
 {
struct device *dev = ks_pcie->pci->dev;
@@ -835,12 +907,17 @@ static int __init ks_pcie_host_init(struct pcie_port *pp)
int ret;
 
pp->bridge->ops = _pcie_ops;
-   if (!ks_pcie->is_am6)
-   pp->bridge->child_ops = _child_pcie_ops;
 
-   ret = ks_pcie_config_legacy_irq(ks_pcie);
-   if (ret)
-   return ret;
+   if (!ks_pcie->is_am6) {
+   pp->bridge->child_ops = _child_pcie_ops;
+   ret = ks_pcie_config_legacy_irq(ks_pcie);
+   if (ret)
+   return ret;
+   } else {
+   ret = ks_pcie_am654_config_legacy_irq(ks_pcie);
+   if (ret)
+   return ret;
+   }
 
ret = ks_pcie_config_msi_irq(ks_pcie);
if (ret)
-- 
2.17.1



[PATCH 2/6] dt-bindings: PCI: ti,am65: Add PCIe endpoint mode dt-bindings for TI's AM65 SoC

2021-03-25 Thread Kishon Vijay Abraham I
Add PCIe endpoint mode dt-bindings for TI's AM65 SoC.

Signed-off-by: Kishon Vijay Abraham I 
---
 .../bindings/pci/ti,am65-pci-ep.yaml  | 80 +++
 1 file changed, 80 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pci/ti,am65-pci-ep.yaml

diff --git a/Documentation/devicetree/bindings/pci/ti,am65-pci-ep.yaml 
b/Documentation/devicetree/bindings/pci/ti,am65-pci-ep.yaml
new file mode 100644
index ..f0a5518e6331
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/ti,am65-pci-ep.yaml
@@ -0,0 +1,80 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2021 Texas Instruments Incorporated - http://www.ti.com/
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/pci/ti,am65-pci-ep.yaml#;
+$schema: "http://devicetree.org/meta-schemas/core.yaml#;
+
+title: TI AM65 PCI Endpoint
+
+maintainers:
+  - Kishon Vijay Abraham I 
+
+allOf:
+  - $ref: "pci-ep.yaml#"
+
+properties:
+  compatible:
+enum:
+  - ti,am654-pcie-ep
+
+  reg:
+maxItems: 4
+
+  reg-names:
+items:
+  - const: app
+  - const: dbics
+  - const: addr_space
+  - const: atu
+
+  power-domains:
+maxItems: 1
+
+  ti,syscon-pcie-mode:
+description: Phandle to the SYSCON entry required for configuring PCIe in 
RC or EP mode.
+$ref: /schemas/types.yaml#/definitions/phandle
+
+  interrupts:
+minItems: 1
+
+  dma-coherent: true
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - max-link-speed
+  - num-lanes
+  - power-domains
+  - ti,syscon-pcie-mode
+  - phys
+  - phy-names
+  - dma-coherent
+
+unevaluatedProperties: false
+
+examples:
+  - |
+#include 
+#include 
+
+bus {
+#address-cells = <2>;
+#size-cells = <2>;
+
+pcie0_ep: pcie-ep@550 {
+compatible = "ti,am654-pcie-ep";
+reg =  <0x0 0x550 0x0 0x1000>,
+   <0x0 0x5501000 0x0 0x1000>,
+   <0x0 0x1000 0x0 0x800>,
+   <0x0 0x5506000 0x0 0x1000>;
+reg-names = "app", "dbics", "addr_space", "atu";
+power-domains = <_pds 120 TI_SCI_PD_EXCLUSIVE>;
+ti,syscon-pcie-mode = <_mode>;
+num-ib-windows = <16>;
+num-ob-windows = <16>;
+max-link-speed = <2>;
+dma-coherent;
+interrupts = ;
+};
-- 
2.17.1



[PATCH 3/6] irqdomain: Export of_phandle_args_to_fwspec()

2021-03-25 Thread Kishon Vijay Abraham I
Export of_phandle_args_to_fwspec() to be used by drivers.
of_phandle_args_to_fwspec() can be used by drivers to get irq specifier
from device node useful while creating hierarchy domain. This was
suggested by Marc Zyngier [1].

[1] -> http://lore.kernel.org/r/20190223121143.14c1f...@why.wild-wind.fr.eu.org/
Signed-off-by: Kishon Vijay Abraham I 
---
 include/linux/irqdomain.h | 2 ++
 kernel/irq/irqdomain.c| 6 +++---
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 42d196805f58..0236f508259e 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -391,6 +391,8 @@ extern void irq_domain_associate_many(struct irq_domain 
*domain,
 extern unsigned int irq_create_mapping_affinity(struct irq_domain *host,
  irq_hw_number_t hwirq,
  const struct irq_affinity_desc *affinity);
+void of_phandle_args_to_fwspec(struct device_node *np, const u32 *args, 
unsigned int count,
+  struct irq_fwspec *fwspec);
 extern unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec);
 extern void irq_dispose_mapping(unsigned int virq);
 
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 288151393a06..70f050741ab2 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -756,9 +756,8 @@ static int irq_domain_translate(struct irq_domain *d,
return 0;
 }
 
-static void of_phandle_args_to_fwspec(struct device_node *np, const u32 *args,
- unsigned int count,
- struct irq_fwspec *fwspec)
+void of_phandle_args_to_fwspec(struct device_node *np, const u32 *args, 
unsigned int count,
+  struct irq_fwspec *fwspec)
 {
int i;
 
@@ -768,6 +767,7 @@ static void of_phandle_args_to_fwspec(struct device_node 
*np, const u32 *args,
for (i = 0; i < count; i++)
fwspec->param[i] = args[i];
 }
+EXPORT_SYMBOL_GPL(of_phandle_args_to_fwspec);
 
 unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
 {
-- 
2.17.1



[PATCH 0/6] PCI: Add legacy interrupt support in Keystone

2021-03-25 Thread Kishon Vijay Abraham I
Keystone driver is used by K2G and AM65 and the interrupt handling of
both of them is different. Add support to handle legacy interrupt for
both K2G and AM65 here.

Some discussions regarding this was already done here [1] and it was
around having pulse interrupt for legacy interrupt.

The HW interrupt line connected to GIC is a pulse interrupt whereas
the legacy interrupts by definition is level interrupt. In order to
provide level interrupt functionality to edge interrupt line, PCIe
in AM654 has provided IRQ_EOI register. When the SW writes to IRQ_EOI
register after handling the interrupt, the IP checks the state of
legacy interrupt and re-triggers pulse interrupt invoking the handler
again.

Patch series also includes converting AM65 binding to YAML and an
errata applicable for i2037.

[1] -> 
https://lore.kernel.org/linux-arm-kernel/20190221101518.22604-4-kis...@ti.com/

Kishon Vijay Abraham I (6):
  dt-bindings: PCI: ti,am65: Add PCIe host mode dt-bindings for TI's
AM65 SoC
  dt-bindings: PCI: ti,am65: Add PCIe endpoint mode dt-bindings for TI's
AM65 SoC
  irqdomain: Export of_phandle_args_to_fwspec()
  PCI: keystone: Convert to using hierarchy domain for legacy interrupts
  PCI: keystone: Add PCI legacy interrupt support for AM654
  PCI: keystone: Add workaround for Errata #i2037 (AM65x SR 1.0)

 .../bindings/pci/ti,am65-pci-ep.yaml  |  80 
 .../bindings/pci/ti,am65-pci-host.yaml| 111 ++
 drivers/pci/controller/dwc/pci-keystone.c | 343 +-
 include/linux/irqdomain.h |   2 +
 kernel/irq/irqdomain.c|   6 +-
 5 files changed, 440 insertions(+), 102 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/pci/ti,am65-pci-ep.yaml
 create mode 100644 Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml

-- 
2.17.1



[PATCH 1/6] dt-bindings: PCI: ti,am65: Add PCIe host mode dt-bindings for TI's AM65 SoC

2021-03-25 Thread Kishon Vijay Abraham I
Add PCIe host mode dt-bindings for TI's AM65 SoC.

Signed-off-by: Kishon Vijay Abraham I 
---
 .../bindings/pci/ti,am65-pci-host.yaml| 111 ++
 1 file changed, 111 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml

diff --git a/Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml 
b/Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml
new file mode 100644
index ..b77e492886fa
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml
@@ -0,0 +1,111 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2021 Texas Instruments Incorporated - http://www.ti.com/
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/pci/ti,am65-pci-host.yaml#;
+$schema: "http://devicetree.org/meta-schemas/core.yaml#;
+
+title: TI AM65 PCI Host
+
+maintainers:
+  - Kishon Vijay Abraham I 
+
+allOf:
+  - $ref: /schemas/pci/pci-bus.yaml#
+
+properties:
+  compatible:
+enum:
+  - ti,am654-pcie-rc
+
+  reg:
+maxItems: 4
+
+  reg-names:
+items:
+  - const: app
+  - const: dbics
+  - const: config
+  - const: atu
+
+  power-domains:
+maxItems: 1
+
+  ti,syscon-pcie-id:
+description: Phandle to the SYSCON entry required for getting PCIe 
device/vendor ID
+$ref: /schemas/types.yaml#/definitions/phandle
+
+  ti,syscon-pcie-mode:
+description: Phandle to the SYSCON entry required for configuring PCIe in 
RC or EP mode.
+$ref: /schemas/types.yaml#/definitions/phandle
+
+  msi-map: true
+
+  dma-coherent: true
+
+patternProperties:
+  "interrupt-controller":
+type: object
+description: interrupt controller to handle legacy interrupts.
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - max-link-speed
+  - num-lanes
+  - power-domains
+  - ti,syscon-pcie-id
+  - ti,syscon-pcie-mode
+  - msi-map
+  - ranges
+  - reset-gpios
+  - phys
+  - phy-names
+  - dma-coherent
+
+unevaluatedProperties: false
+
+examples:
+  - |
+#include 
+#include 
+
+bus {
+#address-cells = <2>;
+#size-cells = <2>;
+
+pcie0_rc: pcie@550 {
+compatible = "ti,am654-pcie-rc";
+reg =  <0x0 0x550 0x0 0x1000>,
+   <0x0 0x5501000 0x0 0x1000>,
+   <0x0 0x1000 0x0 0x2000>,
+   <0x0 0x5506000 0x0 0x1000>;
+reg-names = "app", "dbics", "config", "atu";
+power-domains = <_pds 120 TI_SCI_PD_EXCLUSIVE>;
+#address-cells = <3>;
+#size-cells = <2>;
+ranges = <0x8100 0 0  0x0 0x1002 0 0x0001>,
+ <0x8200 0 0x1003 0x0 0x1003 0 0x07FD>;
+ti,syscon-pcie-id = <_devid>;
+ti,syscon-pcie-mode = <_mode>;
+bus-range = <0x0 0xff>;
+num-viewport = <16>;
+max-link-speed = <2>;
+dma-coherent;
+interrupts = ;
+msi-map = <0x0 _its 0x0 0x1>;
+#interrupt-cells = <1>;
+interrupt-map-mask = <0 0 0 7>;
+interrupt-map = <0 0 0 1 _intc 0>, /* INT A */
+<0 0 0 2 _intc 0>, /* INT B */
+<0 0 0 3 _intc 0>, /* INT C */
+<0 0 0 4 _intc 0>; /* INT D */
+
+pcie0_intc: interrupt-controller {
+interrupt-controller;
+#interrupt-cells = <1>;
+interrupt-parent = <>;
+interrupts = ;
+};
+};
-- 
2.17.1



[PATCH 2/2] PCI: keystone: Add link up check in ks_child_pcie_ops.map_bus()

2021-03-24 Thread Kishon Vijay Abraham I
K2G forwardS the error triggered by a link-down state (e.g.,
no connected endpoint device) on the system bus for PCI configuration
transactions; these errors are reported as an SError at system level,
which is fatal and hangs the system. So fix it similar to how
it was done in designware core driver
commit 15b23906347c ("PCI: dwc: Add link up check in
dw_child_pcie_ops.map_bus()").

Fixes: 10a797c6e54a ("PCI: dwc: keystone: Use pci_ops for config space 
accessors")
Signed-off-by: Kishon Vijay Abraham I 
Cc:  # v5.10
---
 drivers/pci/controller/dwc/pci-keystone.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c 
b/drivers/pci/controller/dwc/pci-keystone.c
index 7171ea70da49..4de8c8e5e3f2 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -432,6 +432,17 @@ static void __iomem *ks_pcie_other_map_bus(struct pci_bus 
*bus,
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
u32 reg;
 
+   /*
+* Checking whether the link is up here is a last line of defense
+* against platforms that forward errors on the system bus as
+* SError upon PCI configuration transactions issued when the link
+* is down. This check is racy by definition and does not stop
+* the system from triggering an SError if the link goes down
+* after this check is performed.
+*/
+   if (!dw_pcie_link_up(pci))
+   return NULL;
+
reg = CFG_BUS(bus->number) | CFG_DEVICE(PCI_SLOT(devfn)) |
CFG_FUNC(PCI_FUNC(devfn));
if (!pci_is_root_bus(bus->parent))
-- 
2.17.1



[PATCH 0/2] PCI: Fixes in pci-keystone driver

2021-03-24 Thread Kishon Vijay Abraham I
Patch series includes a couple of fixes in pci-keystone driver
for issues seen when testing Root Complex mode in K2G driver.

Kishon Vijay Abraham I (2):
  PCI: keystone: Set mode as RootComplex for "ti,keystone-pcie"
compatible
  PCI: keystone: Add link up check in ks_child_pcie_ops.map_bus()

 drivers/pci/controller/dwc/pci-keystone.c | 12 
 1 file changed, 12 insertions(+)

-- 
2.17.1



[PATCH 1/2] PCI: keystone: Set mode as RootComplex for "ti,keystone-pcie" compatible

2021-03-24 Thread Kishon Vijay Abraham I
commit 23284ad677a9 ("PCI: keystone: Add support for PCIe EP in AM654x
Platforms") introduced configuring "enum dw_pcie_device_mode" as part of
device data ("struct ks_pcie_of_data"). However it failed to set mode
for "ti,keystone-pcie" compatible. Set mode as RootComplex for
"ti,keystone-pcie" compatible here.

Fixes: 23284ad677a9 ("PCI: keystone: Add support for PCIe EP in AM654x 
Platforms")
Signed-off-by: Kishon Vijay Abraham I 
Cc:  # v5.4+
---
 drivers/pci/controller/dwc/pci-keystone.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c 
b/drivers/pci/controller/dwc/pci-keystone.c
index a59ecbec601f..7171ea70da49 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -1047,6 +1047,7 @@ static int ks_pcie_am654_set_mode(struct device *dev,
 
 static const struct ks_pcie_of_data ks_pcie_rc_of_data = {
.host_ops = _pcie_host_ops,
+   .mode = DW_PCIE_RC_TYPE,
.version = 0x365A,
 };
 
-- 
2.17.1



Re: [PATCH RESEND] PCI: dwc: Fix MSI not work after resume

2021-03-23 Thread Kishon Vijay Abraham I
Hi,

On 23/03/21 8:42 pm, Bjorn Helgaas wrote:
> [-cc Dilip (mail to him bounced)]
> 
> On Tue, Mar 23, 2021 at 11:01:15AM +0800, Jisheng Zhang wrote:
>> On Mon, 22 Mar 2021 20:24:41 -0500 Bjorn Helgaas wrote:
>>>
>>> [+cc Kishon, Richard, Lucas, Dilip]
>>>
>>> On Mon, Mar 01, 2021 at 11:10:31AM +0800, Jisheng Zhang wrote:
 After we move dw_pcie_msi_init() into core -- dw_pcie_host_init(), the
 MSI stops working after resume. Because dw_pcie_host_init() is only
 called once during probe. To fix this issue, we move dw_pcie_msi_init()
 to dw_pcie_setup_rc().  
>>>
>>> This patch looks fine, but I don't think the commit log tells the
>>> whole story.
>>>
>>> Prior to 59fbab1ae40e, it looks like the only dwc-based drivers with
>>> resume functions were dra7xx, imx6, intel-gw, and tegra [1].
>>>
>>> Only tegra called dw_pcie_msi_init() in the resume path, and I do
>>> think 59fbab1ae40e broke MSI after resume because it removed the
>>> dw_pcie_msi_init() call from tegra_pcie_enable_msi_interrupts().
>>>
>>> I'm not convinced this patch fixes it reliably, though.  The call
>>> chain looks like this:
>>>
>>>   tegra_pcie_dw_resume_noirq
>>> tegra_pcie_dw_start_link
>>>   if (dw_pcie_wait_for_link(pci))
>>> dw_pcie_setup_rc
>>>
>>> dw_pcie_wait_for_link() returns 0 if the link is up, so we only call
>>> dw_pcie_setup_rc() in the case where the link *didn't* come up.  If
>>> the link comes up nicely without retry, we won't call
>>> dw_pcie_setup_rc() and hence won't call dw_pcie_msi_init().
>>
>> The v1 version patch was sent before commit 275e88b06a (PCI: tegra: Fix host
>> link initialization"). At that time, the resume path looks like this:
>>
>> tegra_pcie_dw_resume_noirq
>>   tegra_pcie_dw_host_init
>> tegra_pcie_prepare_host
>>   dw_pcie_setup_rc
>>
>> so after patch, dw_pcie_msi_init() will be called. But now it seems that
>> the tegra version needs one more fix for the resume.
>>
>> So could I sent a new patch to update the commit-msg a bit?
> 
> This patch only touches the dwc core, and the commit log says
> generically that it fixes MSI after resume, so one could assume that
> it applies to all dwc-based drivers.  But I don't think it's that
> simple, so I'd like to know *which* drivers are fixed and which
> commits are related.  I don't see how 59fbab1ae40e breaks anything
> except tegra.
> 
>>> Since then, exynos added a resume function.  My guess is MSI never
>>> worked after resume for dra7xx, exynos, imx6, and intel-gw because
>>> they don't call dw_pcie_msi_init() in their resume functions.
>>>
>>> This patch looks like it should fix MSI after resume for exynos, imx6,
>>> and intel-gw because they *do* call dw_pcie_setup_rc() from their
>>> resume functions [2], and after this patch, dw_pcie_msi_init() will be
>>> called from there.
>>>
>>> I suspect MSI after resume still doesn't work on dra7xx.
>>
>> I checked the dra7xx history, I'm afraid that the resume never works
>> from the beginning if the host lost power during suspend, I guess the
>> platform never power off the host but only the phy?

Suspend on dra7xx disabled clocks and powered off phy (at-least while
suspend/resume hooks were merged) and resume enabled clocks and phy.
However suspend/resume is broken in dra7xx system and is not validated.
I'll send a patch to remove the suspend/resume hooks in dra7xx.

Thanks
Kishon

> 
> Sounds like that would make sense.
> 
>>> [1] git grep -A20 -e "static.*resume_noirq" 
>>> 59fbab1ae40e^:drivers/pci/controller/dwc
>>> [2] git grep -A20 -e "static.*resume_noirq" drivers/pci/controller/dwc
>>>
 Fixes: 59fbab1ae40e ("PCI: dwc: Move dw_pcie_msi_init() into core")
 Reviewed-by: Rob Herring 
 Signed-off-by: Jisheng Zhang 
 ---
 Since v1:
  - collect Reviewed-by tag

  drivers/pci/controller/dwc/pcie-designware-host.c | 3 ++-
  1 file changed, 2 insertions(+), 1 deletion(-)

 diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c 
 b/drivers/pci/controller/dwc/pcie-designware-host.c
 index 7e55b2b66182..e6c274f4485c 100644
 --- a/drivers/pci/controller/dwc/pcie-designware-host.c
 +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
 @@ -400,7 +400,6 @@ int dw_pcie_host_init(struct pcie_port *pp)
   }

   dw_pcie_setup_rc(pp);
 - dw_pcie_msi_init(pp);

   if (!dw_pcie_link_up(pci) && pci->ops && pci->ops->start_link) {
   ret = pci->ops->start_link(pci);
 @@ -551,6 +550,8 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
   }
   }

 + dw_pcie_msi_init(pp);
 +
   /* Setup RC BARs */
   dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0x0004);
   dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_1, 0x);
 --
 2.30.1
  
>>


Re: [PATCH v7 3/3] arm64: dts: ti: k3-j7200: Add support for higher speed modes and update delay select values for MMCSD subsystems

2021-03-23 Thread Kishon Vijay Abraham I
Hi Aswath,

On 23/03/21 10:54 am, Aswath Govindraju wrote:
> Hi Nishanth,
> 
> On 22/03/21 9:05 pm, Nishanth Menon wrote:
>> On 18:42-20210322, Aswath Govindraju wrote:
>>> The following speed modes are now supported in J7200 SoC,
>>> - HS200 and HS400 modes at 1.8 V card voltage, in MMCSD0 subsystem [1].
>>> - UHS-I speed modes in MMCSD1 subsystem [1].
>>>
>>> Add support for UHS-I modes by adding voltage regulator device tree nodes
>>> and corresponding pinmux details, to power cycle and voltage switch cards.
>>> Set respective tags in sdhci0 and remove no-1-8-v tag from sdhci1
>>> device tree nodes.
>>>
>>> Also update the delay values for various speed modes supported, based on
>>> the revised january 2021 J7200 datasheet[2].
>>>
>>> [1] - section 12.3.6.1.1 MMCSD Features, in
>>>   https://www.ti.com/lit/ug/spruiu1a/spruiu1a.pdf,
>>>   (SPRUIU1A – JULY 2020 – REVISED JANUARY 2021)
>>>
>>> [2] - https://www.ti.com/lit/ds/symlink/dra821u.pdf,
>>>   (SPRSP57B – APRIL 2020 – REVISED JANUARY 2021)
>>>
>>> Signed-off-by: Aswath Govindraju 
>>> ---
>>>  .../dts/ti/k3-j7200-common-proc-board.dts | 42 +++
>>>  arch/arm64/boot/dts/ti/k3-j7200-main.dtsi | 14 ++-
>>>  2 files changed, 54 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts 
>>> b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts
>>> index b493f939b09a..de8c06bdc825 100644
>>> --- a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts
>>> +++ b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts
>>> @@ -16,6 +16,29 @@
>>> stdout-path = "serial2:115200n8";
>>> bootargs = "console=ttyS2,115200n8 
>>> earlycon=ns16550a,mmio32,0x0280";
>>> };
>>> +
>>> +   vdd_mmc1: fixedregulator-sd {
>>> +   compatible = "regulator-fixed";
>>> +   regulator-name = "vdd_mmc1";
>>> +   regulator-min-microvolt = <330>;
>>> +   regulator-max-microvolt = <330>;
>>> +   regulator-boot-on;
>>> +   enable-active-high;
>>> +   gpios = < 2 GPIO_ACTIVE_HIGH>;
>>
>> is that gpio ?
> 
> Yes, that is correct. I'll correct it in the respin
> 
>> I'd encourage to use vin-supply as well.
> 
> Will add this in respin.
> 
>>
>>> +   };
>>> +
>>> +   vdd_sd_dv: gpio-regulator-vdd-sd-dv {
>>  What does this drive? TLV71033 ?
> 
> Yes, this node models the TLV71033 voltage regulator that switches the
> MMC IO signal voltage level between 3.3V and 1.8V.

Nope. Unlike J721e SOM which uses TLV71033 for switching voltage, J7200
SOM directly uses GPIO input to PMIC to control the output voltage. So
this should model the gpio input to PMIC.

Thanks
Kishon


Re: [PATCH 1/2] arm64: dts: ti: k3-am64: Add SERDES DT node

2021-03-19 Thread Kishon Vijay Abraham I
Hi Aswath,

On 19/03/21 1:30 pm, Aswath Govindraju wrote:
> From: Kishon Vijay Abraham I 
> 
> Add SERDES DT node for the single one lane SERDES present in
> AM64.
> 
> Signed-off-by: Kishon Vijay Abraham I 
> Signed-off-by: Aswath Govindraju 
> ---
>  arch/arm64/boot/dts/ti/k3-am64-main.dtsi | 52 
>  1 file changed, 52 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/ti/k3-am64-main.dtsi 
> b/arch/arm64/boot/dts/ti/k3-am64-main.dtsi
> index a03b66456062..5a62a96c048c 100644
> --- a/arch/arm64/boot/dts/ti/k3-am64-main.dtsi
> +++ b/arch/arm64/boot/dts/ti/k3-am64-main.dtsi
> @@ -5,6 +5,17 @@
>   * Copyright (C) 2020-2021 Texas Instruments Incorporated - 
> https://www.ti.com/
>   */
>  
> +#include 

One of my patches in other series which renames the header file will
cause issues here :-/
http://lore.kernel.org/r/20210319124128.13308-9-kis...@ti.com

We'll need a immutable tag for this as well.
> +#include 
> +
> +/ {
> + serdes_refclk: serdes-refclk {
> + #clock-cells = <0>;
> + compatible = "fixed-clock";
> + clock-frequency = <1>;
> + };

Clock frequency of serdes_refclk depends on how it is tied in the EVM.
In the case of AM64EVM there is no external clock generator.

It should be something like in
https://github.com/kishon/linux-wip/commit/e5196b0819d334ce8a21b398b7c47557a145d250

Thanks
Kishon

> +};
> +
>  _main {
>   oc_sram: sram@7000 {
>   compatible = "mmio-sram";
> @@ -184,6 +195,12 @@
>   reg = <0x4044 0x8>;
>   #phy-cells = <1>;
>   };
> +
> + serdes_ln_ctrl: mux {
> + compatible = "mmio-mux";
> + #mux-control-cells = <1>;
> + mux-reg-masks = <0x4080 0x3>; /* SERDES0 lane0 select */
> + };
>   };
>  
>   main_uart0: serial@280 {
> @@ -477,6 +494,41 @@
>   };
>   };
>  
> + serdes_wiz0: wiz@f00 {
> + compatible = "ti,am64-wiz-10g";
> + #address-cells = <1>;
> + #size-cells = <1>;
> + power-domains = <_pds 162 TI_SCI_PD_EXCLUSIVE>;
> + clocks = <_clks 162 0>, <_clks 162 1>, <_refclk>;
> + clock-names = "fck", "core_ref_clk", "ext_ref_clk";
> + num-lanes = <1>;
> + #reset-cells = <1>;
> + #clock-cells = <1>;
> + ranges = <0x0f00 0x0 0x0f00 0x0001>;
> + assigned-clocks = <_clks 162 1>;
> + assigned-clock-parents = <_clks 162 5>;
> +
> + serdes0: serdes@f00 {
> + compatible = "ti,j721e-serdes-10g";
> + reg = <0x0f00 0x0001>;
> + reg-names = "torrent_phy";
> + resets = <_wiz0 0>;
> + reset-names = "torrent_reset";
> + clocks = <_wiz0 TI_WIZ_PLL0_REFCLK>,
> +  <_wiz0 TI_WIZ_PHY_EN_REFCLK>;
> + clock-names = "refclk", "phy_en_refclk";
> + assigned-clocks = <_wiz0 TI_WIZ_PLL0_REFCLK>,
> +   <_wiz0 TI_WIZ_PLL1_REFCLK>,
> +   <_wiz0 TI_WIZ_REFCLK_DIG>;
> + assigned-clock-parents = <_clks 162 1>,
> +  <_clks 162 1>,
> +  <_clks 162 1>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> + #clock-cells = <1>;
> + };
> + };
> +
>   cpts@3900 {
>   compatible = "ti,j721e-cpts";
>   reg = <0x0 0x3900 0x0 0x400>;
> 


[PATCH v7 10/13] phy: cadence: Sierra: Add missing clk_disable_unprepare() in .remove callback

2021-03-19 Thread Kishon Vijay Abraham I
commit 44d30d622821 ("phy: cadence: Add driver for Sierra PHY") enabled
the clock in probe and failed to disable in remove callback. Add missing
clk_disable_unprepare() in cdns_sierra_phy_remove().

Fixes: 44d30d622821 ("phy: cadence: Add driver for Sierra PHY")
Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/phy/cadence/phy-cadence-sierra.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/phy/cadence/phy-cadence-sierra.c 
b/drivers/phy/cadence/phy-cadence-sierra.c
index a45278c30948..ac32b7b0289f 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -689,6 +689,9 @@ static int cdns_sierra_phy_remove(struct platform_device 
*pdev)
reset_control_assert(phy->phys[i].lnk_rst);
reset_control_put(phy->phys[i].lnk_rst);
}
+
+   clk_disable_unprepare(phy->input_clks[PHY_CLK]);
+
return 0;
 }
 
-- 
2.17.1



[PATCH v7 11/13] dt-bindings: phy: phy-cadence-sierra: Add binding to model Sierra as clock provider

2021-03-19 Thread Kishon Vijay Abraham I
Add #clock-cells binding to model Sierra as clock provider and include
clock IDs for PLL_CMNLC and PLL_CMNLC1.

Signed-off-by: Kishon Vijay Abraham I 
Reviewed-by: Rob Herring 
---
 .../bindings/phy/phy-cadence-sierra.yaml| 17 -
 include/dt-bindings/phy/phy-cadence.h   |  4 
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/phy/phy-cadence-sierra.yaml 
b/Documentation/devicetree/bindings/phy/phy-cadence-sierra.yaml
index d210843863df..84383e2e0b34 100644
--- a/Documentation/devicetree/bindings/phy/phy-cadence-sierra.yaml
+++ b/Documentation/devicetree/bindings/phy/phy-cadence-sierra.yaml
@@ -26,6 +26,9 @@ properties:
   '#size-cells':
 const: 0
 
+  '#clock-cells':
+const: 1
+
   resets:
 minItems: 1
 maxItems: 2
@@ -49,12 +52,24 @@ properties:
 const: serdes
 
   clocks:
-maxItems: 2
+minItems: 2
+maxItems: 4
 
   clock-names:
+minItems: 2
 items:
   - const: cmn_refclk_dig_div
   - const: cmn_refclk1_dig_div
+  - const: pll0_refclk
+  - const: pll1_refclk
+
+  assigned-clocks:
+minItems: 1
+maxItems: 2
+
+  assigned-clock-parents:
+minItems: 1
+maxItems: 2
 
   cdns,autoconf:
 type: boolean
diff --git a/include/dt-bindings/phy/phy-cadence.h 
b/include/dt-bindings/phy/phy-cadence.h
index 4a5ea52a856f..4652bcb86265 100644
--- a/include/dt-bindings/phy/phy-cadence.h
+++ b/include/dt-bindings/phy/phy-cadence.h
@@ -13,4 +13,8 @@
 
 #define CDNS_TORRENT_REFCLK_DRIVER  0
 
+/* Sierra */
+#define CDNS_SIERRA_PLL_CMNLC  0
+#define CDNS_SIERRA_PLL_CMNLC1 1
+
 #endif /* _DT_BINDINGS_CADENCE_SERDES_H */
-- 
2.17.1



[PATCH v7 12/13] phy: cadence: Sierra: Model PLL_CMNLC and PLL_CMNLC1 as clocks (mux clocks)

2021-03-19 Thread Kishon Vijay Abraham I
Sierra has two PLLs, PLL_CMNLC and PLL_CMNLC1 and each of these PLLs has
two inputs, plllc_refclk (input from pll0_refclk) and refrcv (input from
pll1_refclk). Model PLL_CMNLC and PLL_CMNLC1 as clocks so that it's
possible to select one of these two inputs from device tree.

Signed-off-by: Kishon Vijay Abraham I 
Reviewed-by: Swapnil Jakhade 
---
 drivers/phy/cadence/Kconfig  |   1 +
 drivers/phy/cadence/phy-cadence-sierra.c | 267 ++-
 2 files changed, 265 insertions(+), 3 deletions(-)

diff --git a/drivers/phy/cadence/Kconfig b/drivers/phy/cadence/Kconfig
index 27e9d6c377e5..a62910ff5591 100644
--- a/drivers/phy/cadence/Kconfig
+++ b/drivers/phy/cadence/Kconfig
@@ -25,6 +25,7 @@ config PHY_CADENCE_DPHY
 config PHY_CADENCE_SIERRA
tristate "Cadence Sierra PHY Driver"
depends on OF && HAS_IOMEM && RESET_CONTROLLER
+   depends on COMMON_CLK
select GENERIC_PHY
help
  Enable this to support the Cadence Sierra PHY driver
diff --git a/drivers/phy/cadence/phy-cadence-sierra.c 
b/drivers/phy/cadence/phy-cadence-sierra.c
index ac32b7b0289f..039ca10db59d 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -7,6 +7,7 @@
  *
  */
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -20,10 +21,12 @@
 #include 
 #include 
 #include 
+#include 
 
 /* PHY register offsets */
 #define SIERRA_COMMON_CDB_OFFSET   0x0
 #define SIERRA_MACRO_ID_REG0x0
+#define SIERRA_CMN_PLLLC_GEN_PREG  0x42
 #define SIERRA_CMN_PLLLC_MODE_PREG 0x48
 #define SIERRA_CMN_PLLLC_LF_COEFF_MODE1_PREG   0x49
 #define SIERRA_CMN_PLLLC_LF_COEFF_MODE0_PREG   0x4A
@@ -31,6 +34,9 @@
 #define SIERRA_CMN_PLLLC_BWCAL_MODE1_PREG  0x4F
 #define SIERRA_CMN_PLLLC_BWCAL_MODE0_PREG  0x50
 #define SIERRA_CMN_PLLLC_SS_TIME_STEPSIZE_MODE_PREG0x62
+#define SIERRA_CMN_REFRCV_PREG 0x98
+#define SIERRA_CMN_REFRCV1_PREG0xB8
+#define SIERRA_CMN_PLLLC1_GEN_PREG 0xC2
 
 #define SIERRA_LANE_CDB_OFFSET(ln, block_offset, reg_offset)   \
((0x4000 << (block_offset)) + \
@@ -144,13 +150,19 @@
 #define SIERRA_MAX_LANES   16
 #define PLL_LOCK_TIME  10
 
-#define CDNS_SIERRA_INPUT_CLOCKS   3
+#define CDNS_SIERRA_OUTPUT_CLOCKS  2
+#define CDNS_SIERRA_INPUT_CLOCKS   5
 enum cdns_sierra_clock_input {
PHY_CLK,
CMN_REFCLK_DIG_DIV,
CMN_REFCLK1_DIG_DIV,
+   PLL0_REFCLK,
+   PLL1_REFCLK,
 };
 
+#define SIERRA_NUM_CMN_PLLC2
+#define SIERRA_NUM_CMN_PLLC_PARENTS2
+
 static const struct reg_field macro_id_type =
REG_FIELD(SIERRA_MACRO_ID_REG, 0, 15);
 static const struct reg_field phy_pll_cfg_1 =
@@ -158,6 +170,53 @@ static const struct reg_field phy_pll_cfg_1 =
 static const struct reg_field pllctrl_lock =
REG_FIELD(SIERRA_PLLCTRL_STATUS_PREG, 0, 0);
 
+static const char * const clk_names[] = {
+   [CDNS_SIERRA_PLL_CMNLC] = "pll_cmnlc",
+   [CDNS_SIERRA_PLL_CMNLC1] = "pll_cmnlc1",
+};
+
+enum cdns_sierra_cmn_plllc {
+   CMN_PLLLC,
+   CMN_PLLLC1,
+};
+
+struct cdns_sierra_pll_mux_reg_fields {
+   struct reg_fieldpfdclk_sel_preg;
+   struct reg_fieldplllc1en_field;
+   struct reg_fieldtermen_field;
+};
+
+static const struct cdns_sierra_pll_mux_reg_fields 
cmn_plllc_pfdclk1_sel_preg[] = {
+   [CMN_PLLLC] = {
+   .pfdclk_sel_preg = REG_FIELD(SIERRA_CMN_PLLLC_GEN_PREG, 1, 1),
+   .plllc1en_field = REG_FIELD(SIERRA_CMN_REFRCV1_PREG, 8, 8),
+   .termen_field = REG_FIELD(SIERRA_CMN_REFRCV1_PREG, 0, 0),
+   },
+   [CMN_PLLLC1] = {
+   .pfdclk_sel_preg = REG_FIELD(SIERRA_CMN_PLLLC1_GEN_PREG, 1, 1),
+   .plllc1en_field = REG_FIELD(SIERRA_CMN_REFRCV_PREG, 8, 8),
+   .termen_field = REG_FIELD(SIERRA_CMN_REFRCV_PREG, 0, 0),
+   },
+};
+
+struct cdns_sierra_pll_mux {
+   struct clk_hw   hw;
+   struct regmap_field *pfdclk_sel_preg;
+   struct regmap_field *plllc1en_field;
+   struct regmap_field *termen_field;
+   struct clk_init_dataclk_data;
+};
+
+#define to_cdns_sierra_pll_mux(_hw)\
+   container_of(_hw, struct cdns_sierra_pll_mux, hw)
+
+static const int pll_mux_parent_index[][SIERRA_NUM_CMN_PLLC_PARENTS] = {
+   [CMN_PLLLC] = { PLL0_REFCLK, PLL1_REFCLK },
+   [CMN_PLLLC1] = { PLL1_REFCLK, PLL0_REFCLK },
+};
+
+static u32 cdns_sierra_pll_mux_table[] = { 0, 1 };
+
 struct cdns_sierra_inst {
struct phy *phy

[PATCH v7 09/13] phy: cadence: Sierra: Add array of input clocks in "struct cdns_sierra_phy"

2021-03-19 Thread Kishon Vijay Abraham I
Instead of having separate structure members for each input clock, add
an array for the input clocks within "struct cdns_sierra_phy". This is
in preparation for adding more input clocks required for supporting
additional clock combination.

Signed-off-by: Kishon Vijay Abraham I 
Reviewed-by: Swapnil Jakhade 
---
 drivers/phy/cadence/phy-cadence-sierra.c | 25 ++--
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/drivers/phy/cadence/phy-cadence-sierra.c 
b/drivers/phy/cadence/phy-cadence-sierra.c
index 44c52a0842dc..a45278c30948 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -144,6 +144,13 @@
 #define SIERRA_MAX_LANES   16
 #define PLL_LOCK_TIME  10
 
+#define CDNS_SIERRA_INPUT_CLOCKS   3
+enum cdns_sierra_clock_input {
+   PHY_CLK,
+   CMN_REFCLK_DIG_DIV,
+   CMN_REFCLK1_DIG_DIV,
+};
+
 static const struct reg_field macro_id_type =
REG_FIELD(SIERRA_MACRO_ID_REG, 0, 15);
 static const struct reg_field phy_pll_cfg_1 =
@@ -197,9 +204,7 @@ struct cdns_sierra_phy {
struct regmap_field *macro_id_type;
struct regmap_field *phy_pll_cfg_1;
struct regmap_field *pllctrl_lock[SIERRA_MAX_LANES];
-   struct clk *clk;
-   struct clk *cmn_refclk_dig_div;
-   struct clk *cmn_refclk1_dig_div;
+   struct clk *input_clks[CDNS_SIERRA_INPUT_CLOCKS];
int nsubnodes;
u32 num_lanes;
bool autoconf;
@@ -281,8 +286,8 @@ static int cdns_sierra_phy_init(struct phy *gphy)
if (phy->autoconf)
return 0;
 
-   clk_set_rate(phy->cmn_refclk_dig_div, 2500);
-   clk_set_rate(phy->cmn_refclk1_dig_div, 2500);
+   clk_set_rate(phy->input_clks[CMN_REFCLK_DIG_DIV], 2500);
+   clk_set_rate(phy->input_clks[CMN_REFCLK1_DIG_DIV], 2500);
if (ins->phy_type == PHY_TYPE_PCIE) {
num_cmn_regs = phy->init_data->pcie_cmn_regs;
num_ln_regs = phy->init_data->pcie_ln_regs;
@@ -488,7 +493,7 @@ static int cdns_sierra_phy_get_clocks(struct 
cdns_sierra_phy *sp,
dev_err(dev, "failed to get clock phy_clk\n");
return PTR_ERR(clk);
}
-   sp->clk = clk;
+   sp->input_clks[PHY_CLK] = clk;
 
clk = devm_clk_get_optional(dev, "cmn_refclk_dig_div");
if (IS_ERR(clk)) {
@@ -496,7 +501,7 @@ static int cdns_sierra_phy_get_clocks(struct 
cdns_sierra_phy *sp,
ret = PTR_ERR(clk);
return ret;
}
-   sp->cmn_refclk_dig_div = clk;
+   sp->input_clks[CMN_REFCLK_DIG_DIV] = clk;
 
clk = devm_clk_get_optional(dev, "cmn_refclk1_dig_div");
if (IS_ERR(clk)) {
@@ -504,7 +509,7 @@ static int cdns_sierra_phy_get_clocks(struct 
cdns_sierra_phy *sp,
ret = PTR_ERR(clk);
return ret;
}
-   sp->cmn_refclk1_dig_div = clk;
+   sp->input_clks[CMN_REFCLK1_DIG_DIV] = clk;
 
return 0;
 }
@@ -585,7 +590,7 @@ static int cdns_sierra_phy_probe(struct platform_device 
*pdev)
if (ret)
return ret;
 
-   ret = clk_prepare_enable(sp->clk);
+   ret = clk_prepare_enable(sp->input_clks[PHY_CLK]);
if (ret)
return ret;
 
@@ -662,7 +667,7 @@ static int cdns_sierra_phy_probe(struct platform_device 
*pdev)
reset_control_put(sp->phys[i].lnk_rst);
of_node_put(child);
 clk_disable:
-   clk_disable_unprepare(sp->clk);
+   clk_disable_unprepare(sp->input_clks[PHY_CLK]);
reset_control_assert(sp->apb_rst);
return ret;
 }
-- 
2.17.1



[PATCH v7 07/13] phy: cadence: Sierra: Explicitly request exclusive reset control

2021-03-19 Thread Kishon Vijay Abraham I
No functional change. Since the reset controls obtained in
Sierra is exclusively used by the Sierra device, use
exclusive reset control request API calls.

Signed-off-by: Kishon Vijay Abraham I 
Reviewed-by: Philipp Zabel 
---
 drivers/phy/cadence/phy-cadence-sierra.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/phy/cadence/phy-cadence-sierra.c 
b/drivers/phy/cadence/phy-cadence-sierra.c
index 935f165404e4..44c52a0842dc 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -514,14 +514,14 @@ static int cdns_sierra_phy_get_resets(struct 
cdns_sierra_phy *sp,
 {
struct reset_control *rst;
 
-   rst = devm_reset_control_get(dev, "sierra_reset");
+   rst = devm_reset_control_get_exclusive(dev, "sierra_reset");
if (IS_ERR(rst)) {
dev_err(dev, "failed to get reset\n");
return PTR_ERR(rst);
}
sp->phy_rst = rst;
 
-   rst = devm_reset_control_get_optional(dev, "sierra_apb");
+   rst = devm_reset_control_get_optional_exclusive(dev, "sierra_apb");
if (IS_ERR(rst)) {
dev_err(dev, "failed to get apb reset\n");
return PTR_ERR(rst);
-- 
2.17.1



[PATCH v7 08/13] phy: cadence-torrent: Use a common header file for Cadence SERDES

2021-03-19 Thread Kishon Vijay Abraham I
No functional change. In order to have a single header file for all
Cadence SERDES move phy-cadence-torrent.h to phy-cadence.h. This is
in preparation for adding Cadence Sierra SERDES specific macros.

Signed-off-by: Kishon Vijay Abraham I 
Reviewed-by: Swapnil Jakhade 
---
 .../devicetree/bindings/phy/phy-cadence-torrent.yaml | 2 +-
 drivers/phy/cadence/phy-cadence-torrent.c| 2 +-
 .../phy/{phy-cadence-torrent.h => phy-cadence.h} | 9 +
 3 files changed, 7 insertions(+), 6 deletions(-)
 rename include/dt-bindings/phy/{phy-cadence-torrent.h => phy-cadence.h} (51%)

diff --git a/Documentation/devicetree/bindings/phy/phy-cadence-torrent.yaml 
b/Documentation/devicetree/bindings/phy/phy-cadence-torrent.yaml
index 4608599a31d8..01dcd14e7b2a 100644
--- a/Documentation/devicetree/bindings/phy/phy-cadence-torrent.yaml
+++ b/Documentation/devicetree/bindings/phy/phy-cadence-torrent.yaml
@@ -184,7 +184,7 @@ examples:
 };
   - |
 #include 
-#include 
+#include 
 
 bus {
 #address-cells = <2>;
diff --git a/drivers/phy/cadence/phy-cadence-torrent.c 
b/drivers/phy/cadence/phy-cadence-torrent.c
index 95160da3e667..3fdab0d288c4 100644
--- a/drivers/phy/cadence/phy-cadence-torrent.c
+++ b/drivers/phy/cadence/phy-cadence-torrent.c
@@ -7,7 +7,7 @@
  */
 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
diff --git a/include/dt-bindings/phy/phy-cadence-torrent.h 
b/include/dt-bindings/phy/phy-cadence.h
similarity index 51%
rename from include/dt-bindings/phy/phy-cadence-torrent.h
rename to include/dt-bindings/phy/phy-cadence.h
index 3c92c6192493..4a5ea52a856f 100644
--- a/include/dt-bindings/phy/phy-cadence-torrent.h
+++ b/include/dt-bindings/phy/phy-cadence.h
@@ -1,15 +1,16 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
- * This header provides constants for Cadence Torrent SERDES.
+ * This header provides constants for Cadence SERDES.
  */
 
-#ifndef _DT_BINDINGS_TORRENT_SERDES_H
-#define _DT_BINDINGS_TORRENT_SERDES_H
+#ifndef _DT_BINDINGS_CADENCE_SERDES_H
+#define _DT_BINDINGS_CADENCE_SERDES_H
 
+/* Torrent */
 #define TORRENT_SERDES_NO_SSC  0
 #define TORRENT_SERDES_EXTERNAL_SSC1
 #define TORRENT_SERDES_INTERNAL_SSC2
 
 #define CDNS_TORRENT_REFCLK_DRIVER  0
 
-#endif /* _DT_BINDINGS_TORRENT_SERDES_H */
+#endif /* _DT_BINDINGS_CADENCE_SERDES_H */
-- 
2.17.1



[PATCH v7 06/13] phy: cadence: Sierra: Move all reset_control_get*() to a separate function

2021-03-19 Thread Kishon Vijay Abraham I
No functional change. Group devm_reset_control_get() and
devm_reset_control_get_optional() to a separate function.

Signed-off-by: Kishon Vijay Abraham I 
Reviewed-by: Philipp Zabel 
---
 drivers/phy/cadence/phy-cadence-sierra.c | 36 
 1 file changed, 25 insertions(+), 11 deletions(-)

diff --git a/drivers/phy/cadence/phy-cadence-sierra.c 
b/drivers/phy/cadence/phy-cadence-sierra.c
index 7bf1b4c7774a..935f165404e4 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -509,6 +509,28 @@ static int cdns_sierra_phy_get_clocks(struct 
cdns_sierra_phy *sp,
return 0;
 }
 
+static int cdns_sierra_phy_get_resets(struct cdns_sierra_phy *sp,
+ struct device *dev)
+{
+   struct reset_control *rst;
+
+   rst = devm_reset_control_get(dev, "sierra_reset");
+   if (IS_ERR(rst)) {
+   dev_err(dev, "failed to get reset\n");
+   return PTR_ERR(rst);
+   }
+   sp->phy_rst = rst;
+
+   rst = devm_reset_control_get_optional(dev, "sierra_apb");
+   if (IS_ERR(rst)) {
+   dev_err(dev, "failed to get apb reset\n");
+   return PTR_ERR(rst);
+   }
+   sp->apb_rst = rst;
+
+   return 0;
+}
+
 static int cdns_sierra_phy_probe(struct platform_device *pdev)
 {
struct cdns_sierra_phy *sp;
@@ -559,17 +581,9 @@ static int cdns_sierra_phy_probe(struct platform_device 
*pdev)
if (ret)
return ret;
 
-   sp->phy_rst = devm_reset_control_get(dev, "sierra_reset");
-   if (IS_ERR(sp->phy_rst)) {
-   dev_err(dev, "failed to get reset\n");
-   return PTR_ERR(sp->phy_rst);
-   }
-
-   sp->apb_rst = devm_reset_control_get_optional(dev, "sierra_apb");
-   if (IS_ERR(sp->apb_rst)) {
-   dev_err(dev, "failed to get apb reset\n");
-   return PTR_ERR(sp->apb_rst);
-   }
+   ret = cdns_sierra_phy_get_resets(sp, dev);
+   if (ret)
+   return ret;
 
ret = clk_prepare_enable(sp->clk);
if (ret)
-- 
2.17.1



[PATCH v7 05/13] phy: cadence: Sierra: Move all clk_get_*() to a separate function

2021-03-19 Thread Kishon Vijay Abraham I
No functional change. Group all devm_clk_get_optional() to a
separate function.

Signed-off-by: Kishon Vijay Abraham I 
Reviewed-by: Swapnil Jakhade 
---
 drivers/phy/cadence/phy-cadence-sierra.c | 57 +++-
 1 file changed, 35 insertions(+), 22 deletions(-)

diff --git a/drivers/phy/cadence/phy-cadence-sierra.c 
b/drivers/phy/cadence/phy-cadence-sierra.c
index f7ba0ed416bc..7bf1b4c7774a 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -477,6 +477,38 @@ static int cdns_regmap_init_blocks(struct cdns_sierra_phy 
*sp,
return 0;
 }
 
+static int cdns_sierra_phy_get_clocks(struct cdns_sierra_phy *sp,
+ struct device *dev)
+{
+   struct clk *clk;
+   int ret;
+
+   clk = devm_clk_get_optional(dev, "phy_clk");
+   if (IS_ERR(clk)) {
+   dev_err(dev, "failed to get clock phy_clk\n");
+   return PTR_ERR(clk);
+   }
+   sp->clk = clk;
+
+   clk = devm_clk_get_optional(dev, "cmn_refclk_dig_div");
+   if (IS_ERR(clk)) {
+   dev_err(dev, "cmn_refclk_dig_div clock not found\n");
+   ret = PTR_ERR(clk);
+   return ret;
+   }
+   sp->cmn_refclk_dig_div = clk;
+
+   clk = devm_clk_get_optional(dev, "cmn_refclk1_dig_div");
+   if (IS_ERR(clk)) {
+   dev_err(dev, "cmn_refclk1_dig_div clock not found\n");
+   ret = PTR_ERR(clk);
+   return ret;
+   }
+   sp->cmn_refclk1_dig_div = clk;
+
+   return 0;
+}
+
 static int cdns_sierra_phy_probe(struct platform_device *pdev)
 {
struct cdns_sierra_phy *sp;
@@ -487,7 +519,6 @@ static int cdns_sierra_phy_probe(struct platform_device 
*pdev)
unsigned int id_value;
int i, ret, node = 0;
void __iomem *base;
-   struct clk *clk;
struct device_node *dn = dev->of_node, *child;
 
if (of_get_child_count(dn) == 0)
@@ -524,11 +555,9 @@ static int cdns_sierra_phy_probe(struct platform_device 
*pdev)
 
platform_set_drvdata(pdev, sp);
 
-   sp->clk = devm_clk_get_optional(dev, "phy_clk");
-   if (IS_ERR(sp->clk)) {
-   dev_err(dev, "failed to get clock phy_clk\n");
-   return PTR_ERR(sp->clk);
-   }
+   ret = cdns_sierra_phy_get_clocks(sp, dev);
+   if (ret)
+   return ret;
 
sp->phy_rst = devm_reset_control_get(dev, "sierra_reset");
if (IS_ERR(sp->phy_rst)) {
@@ -542,22 +571,6 @@ static int cdns_sierra_phy_probe(struct platform_device 
*pdev)
return PTR_ERR(sp->apb_rst);
}
 
-   clk = devm_clk_get_optional(dev, "cmn_refclk_dig_div");
-   if (IS_ERR(clk)) {
-   dev_err(dev, "cmn_refclk_dig_div clock not found\n");
-   ret = PTR_ERR(clk);
-   return ret;
-   }
-   sp->cmn_refclk_dig_div = clk;
-
-   clk = devm_clk_get_optional(dev, "cmn_refclk1_dig_div");
-   if (IS_ERR(clk)) {
-   dev_err(dev, "cmn_refclk1_dig_div clock not found\n");
-   ret = PTR_ERR(clk);
-   return ret;
-   }
-   sp->cmn_refclk1_dig_div = clk;
-
ret = clk_prepare_enable(sp->clk);
if (ret)
return ret;
-- 
2.17.1



[PATCH v7 04/13] phy: ti: j721e-wiz: Get PHY properties only for "phy" or "link" subnode

2021-03-19 Thread Kishon Vijay Abraham I
"serdes" node (child node of WIZ) can have sub-nodes for representing links
or it can have sub-nodes for representing the various clocks within the
serdes. Instead of trying to read "reg" from every child node used for
assigning "lane_phy_type", read only if the child node's name is "phy"
or "link" subnode.
Ideally all PHY dt nodes should have node name as "phy", however
existing devicetree used "link" as subnode. So in order to maintain old
DT compatibility get PHY properties for "phy" or "link" subnode.

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/phy/ti/phy-j721e-wiz.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c
index 1bb73822f44a..659597645201 100644
--- a/drivers/phy/ti/phy-j721e-wiz.c
+++ b/drivers/phy/ti/phy-j721e-wiz.c
@@ -1102,6 +1102,10 @@ static int wiz_get_lane_phy_types(struct device *dev, 
struct wiz *wiz)
u32 reg, num_lanes = 1, phy_type = PHY_NONE;
int ret, i;
 
+   if (!(of_node_name_eq(subnode, "phy") ||
+ of_node_name_eq(subnode, "link")))
+   continue;
+
ret = of_property_read_u32(subnode, "reg", );
if (ret) {
dev_err(dev,
-- 
2.17.1



[PATCH v7 03/13] phy: cadence: Sierra: Create PHY only for "phy" or "link" sub-nodes

2021-03-19 Thread Kishon Vijay Abraham I
Cadence Sierra PHY driver registers PHY using devm_phy_create()
for all sub-nodes of Sierra device tree node. However Sierra device
tree node can have sub-nodes for the various clocks in addtion to the
PHY. Use devm_phy_create() only for nodes with name "phy" (or "link"
for old device tree) which represent the actual PHY.

Signed-off-by: Kishon Vijay Abraham I 
Reviewed-by: Swapnil Jakhade 
---
 drivers/phy/cadence/phy-cadence-sierra.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/phy/cadence/phy-cadence-sierra.c 
b/drivers/phy/cadence/phy-cadence-sierra.c
index 19f32ae877b9..f7ba0ed416bc 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -577,6 +577,10 @@ static int cdns_sierra_phy_probe(struct platform_device 
*pdev)
for_each_available_child_of_node(dn, child) {
struct phy *gphy;
 
+   if (!(of_node_name_eq(child, "phy") ||
+ of_node_name_eq(child, "link")))
+   continue;
+
sp->phys[node].lnk_rst =
of_reset_control_array_get_exclusive(child);
 
-- 
2.17.1



[PATCH v7 02/13] phy: ti: j721e-wiz: Invoke wiz_init() before of_platform_device_create()

2021-03-19 Thread Kishon Vijay Abraham I
Invoke wiz_init() before configuring anything else in Sierra/Torrent
(invoked as part of of_platform_device_create()). wiz_init() resets the
SERDES device and any configuration done in the probe() of
Sierra/Torrent will be lost. In order to prevent SERDES configuration
from getting reset, invoke wiz_init() immediately before invoking
of_platform_device_create().

Fixes: 091876cc355d ("phy: ti: j721e-wiz: Add support for WIZ module present in 
TI J721E SoC")
Signed-off-by: Kishon Vijay Abraham I 
Reviewed-by: Swapnil Jakhade 
Cc:  # v5.10
---
 drivers/phy/ti/phy-j721e-wiz.c | 17 +++--
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c
index 995c7dbec77b..1bb73822f44a 100644
--- a/drivers/phy/ti/phy-j721e-wiz.c
+++ b/drivers/phy/ti/phy-j721e-wiz.c
@@ -1262,27 +1262,24 @@ static int wiz_probe(struct platform_device *pdev)
goto err_get_sync;
}
 
+   ret = wiz_init(wiz);
+   if (ret) {
+   dev_err(dev, "WIZ initialization failed\n");
+   goto err_wiz_init;
+   }
+
serdes_pdev = of_platform_device_create(child_node, NULL, dev);
if (!serdes_pdev) {
dev_WARN(dev, "Unable to create SERDES platform device\n");
ret = -ENOMEM;
-   goto err_pdev_create;
-   }
-   wiz->serdes_pdev = serdes_pdev;
-
-   ret = wiz_init(wiz);
-   if (ret) {
-   dev_err(dev, "WIZ initialization failed\n");
goto err_wiz_init;
}
+   wiz->serdes_pdev = serdes_pdev;
 
of_node_put(child_node);
return 0;
 
 err_wiz_init:
-   of_platform_device_destroy(_pdev->dev, NULL);
-
-err_pdev_create:
wiz_clock_cleanup(wiz, node);
 
 err_get_sync:
-- 
2.17.1



[PATCH v7 00/13] PHY: Add support in Sierra to use external clock

2021-03-19 Thread Kishon Vijay Abraham I
Patch series adds support in Sierra driver to use external clock.

v1 of the patch series can be found @ [1]
v2 of the patch series can be found @ [2]
v3 of the patch series can be found @ [3]
v4 of the patch series can be found @ [5]
v5 of the patch series can be found @ [6]
v6 of the patch series can be found @ [7]

Changes from v6:
1) Fixed $subject of patches to just have Sierra
2) Added Reviewed-by Tags
3) Fixed dt-binding example which included phy-cadence-torrent.h

Changes from v5:
1) Added Rob's Reviewed-by for the DT binding
2) Fixed another error handling case pointed out by Swapnil
3) Fixed few checkpatch errors.

Changes from v4:
1) Fixed couple of error handling cases
2) Added reviewed by from Philipp Zabel
3) Fixed couple of patch commit subjects to be uniform with other
patches.

Changes from v3:
1) Instead of adding separate subnodes for each clock, just add
   #clock-cells in Sierra SERDES nodes and model the clocks. This is
in alignment with Rob's comment for a different series [4]
2) Removed device tree changes from the series.

Changes from v2:
1) Add depends on COMMON_CLK in Sierra
2) Add modelling PLL_CMNLC and PLL_CMNLC1 as clocks into a separate
patch
3) Disable clocks in Sierra driver remove

Changes from v1:
1) Remove the part that prevents configuration if the SERDES is already
   configured and focus only on using external clock and the associated
   cleanups
2) Change patch ordering
3) Use exclusive reset control APIs
4) Fix error handling code
5) Include DT patches in this series (I can send this separately to DT
MAINTAINER once the driver patches are merged)

[1] -> http://lore.kernel.org/r/20201103035556.21260-1-kis...@ti.com
[2] -> http://lore.kernel.org/r/20201222070520.28132-1-kis...@ti.com
[3] -> http://lore.kernel.org/r/20201224111627.32590-1-kis...@ti.com
[4] -> http://lore.kernel.org/r/20210108025943.ga1790...@robh.at.kernel.org
[5] -> https://lore.kernel.org/r/20210304044122.15166-1-kis...@ti.com
[6] -> https://lore.kernel.org/r/20210308050732.7140-1-kis...@ti.com
[7] -> http://lore.kernel.org/r/20210310154558.32078-1-kis...@ti.com

Kishon Vijay Abraham I (13):
  phy: cadence: Sierra: Fix PHY power_on sequence
  phy: ti: j721e-wiz: Invoke wiz_init() before
of_platform_device_create()
  phy: cadence: Sierra: Create PHY only for "phy" or "link" sub-nodes
  phy: ti: j721e-wiz: Get PHY properties only for "phy" or "link"
subnode
  phy: cadence: Sierra: Move all clk_get_*() to a separate function
  phy: cadence: Sierra: Move all reset_control_get*() to a separate
function
  phy: cadence: Sierra: Explicitly request exclusive reset control
  phy: cadence-torrent: Use a common header file for Cadence SERDES
  phy: cadence: Sierra: Add array of input clocks in "struct
cdns_sierra_phy"
  phy: cadence: Sierra: Add missing clk_disable_unprepare() in .remove
callback
  dt-bindings: phy: phy-cadence-sierra: Add binding to model Sierra as
clock provider
  phy: cadence: Sierra: Model PLL_CMNLC and PLL_CMNLC1 as clocks (mux
clocks)
  phy: cadence: Sierra: Enable pll_cmnlc and pll_cmnlc1 clocks

 .../bindings/phy/phy-cadence-sierra.yaml  |  17 +-
 .../bindings/phy/phy-cadence-torrent.yaml |   2 +-
 drivers/phy/cadence/Kconfig   |   1 +
 drivers/phy/cadence/phy-cadence-sierra.c  | 419 --
 drivers/phy/cadence/phy-cadence-torrent.c |   2 +-
 drivers/phy/ti/phy-j721e-wiz.c|  21 +-
 include/dt-bindings/phy/phy-cadence-torrent.h |  15 -
 include/dt-bindings/phy/phy-cadence.h |  20 +
 8 files changed, 429 insertions(+), 68 deletions(-)
 delete mode 100644 include/dt-bindings/phy/phy-cadence-torrent.h
 create mode 100644 include/dt-bindings/phy/phy-cadence.h

-- 
2.17.1



[PATCH v7 01/13] phy: cadence: Sierra: Fix PHY power_on sequence

2021-03-19 Thread Kishon Vijay Abraham I
Commit 44d30d622821d ("phy: cadence: Add driver for Sierra PHY")
de-asserts PHY_RESET even before the configurations are loaded in
phy_init(). However PHY_RESET should be de-asserted only after
all the configurations has been initialized, instead of de-asserting
in probe. Fix it here.

Fixes: 44d30d622821d ("phy: cadence: Add driver for Sierra PHY")
Signed-off-by: Kishon Vijay Abraham I 
Cc:  # v5.4+
Reviewed-by: Philipp Zabel 
---
 drivers/phy/cadence/phy-cadence-sierra.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/phy/cadence/phy-cadence-sierra.c 
b/drivers/phy/cadence/phy-cadence-sierra.c
index 26a0badabe38..19f32ae877b9 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -319,6 +319,12 @@ static int cdns_sierra_phy_on(struct phy *gphy)
u32 val;
int ret;
 
+   ret = reset_control_deassert(sp->phy_rst);
+   if (ret) {
+   dev_err(dev, "Failed to take the PHY out of reset\n");
+   return ret;
+   }
+
/* Take the PHY lane group out of reset */
ret = reset_control_deassert(ins->lnk_rst);
if (ret) {
@@ -616,7 +622,6 @@ static int cdns_sierra_phy_probe(struct platform_device 
*pdev)
 
pm_runtime_enable(dev);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-   reset_control_deassert(sp->phy_rst);
return PTR_ERR_OR_ZERO(phy_provider);
 
 put_child:
-- 
2.17.1



[PATCH v7 13/13] phy: cadence: Sierra: Enable pll_cmnlc and pll_cmnlc1 clocks

2021-03-19 Thread Kishon Vijay Abraham I
Get pll_cmnlc and pll_cmnlc1 optional clocks and enable them.
This will enable REFRCV/1 in case the pll_cmnlc/1 takes input
from REFRCV/1 respectively.

Signed-off-by: Kishon Vijay Abraham I 
Reviewed-by: Swapnil Jakhade 
---
 drivers/phy/cadence/phy-cadence-sierra.c | 40 ++--
 1 file changed, 37 insertions(+), 3 deletions(-)

diff --git a/drivers/phy/cadence/phy-cadence-sierra.c 
b/drivers/phy/cadence/phy-cadence-sierra.c
index 039ca10db59d..5c68e31c5939 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -768,6 +768,40 @@ static int cdns_sierra_phy_get_clocks(struct 
cdns_sierra_phy *sp,
return 0;
 }
 
+static int cdns_sierra_phy_enable_clocks(struct cdns_sierra_phy *sp)
+{
+   int ret;
+
+   ret = clk_prepare_enable(sp->input_clks[PHY_CLK]);
+   if (ret)
+   return ret;
+
+   ret = clk_prepare_enable(sp->output_clks[CDNS_SIERRA_PLL_CMNLC]);
+   if (ret)
+   goto err_pll_cmnlc;
+
+   ret = clk_prepare_enable(sp->output_clks[CDNS_SIERRA_PLL_CMNLC1]);
+   if (ret)
+   goto err_pll_cmnlc1;
+
+   return 0;
+
+err_pll_cmnlc1:
+   clk_disable_unprepare(sp->output_clks[CDNS_SIERRA_PLL_CMNLC]);
+
+err_pll_cmnlc:
+   clk_disable_unprepare(sp->input_clks[PHY_CLK]);
+
+   return ret;
+}
+
+static void cdns_sierra_phy_disable_clocks(struct cdns_sierra_phy *sp)
+{
+   clk_disable_unprepare(sp->output_clks[CDNS_SIERRA_PLL_CMNLC1]);
+   clk_disable_unprepare(sp->output_clks[CDNS_SIERRA_PLL_CMNLC]);
+   clk_disable_unprepare(sp->input_clks[PHY_CLK]);
+}
+
 static int cdns_sierra_phy_get_resets(struct cdns_sierra_phy *sp,
  struct device *dev)
 {
@@ -848,7 +882,7 @@ static int cdns_sierra_phy_probe(struct platform_device 
*pdev)
if (ret)
goto unregister_clk;
 
-   ret = clk_prepare_enable(sp->input_clks[PHY_CLK]);
+   ret = cdns_sierra_phy_enable_clocks(sp);
if (ret)
goto unregister_clk;
 
@@ -925,7 +959,7 @@ static int cdns_sierra_phy_probe(struct platform_device 
*pdev)
reset_control_put(sp->phys[i].lnk_rst);
of_node_put(child);
 clk_disable:
-   clk_disable_unprepare(sp->input_clks[PHY_CLK]);
+   cdns_sierra_phy_disable_clocks(sp);
reset_control_assert(sp->apb_rst);
 unregister_clk:
cdns_sierra_clk_unregister(sp);
@@ -941,6 +975,7 @@ static int cdns_sierra_phy_remove(struct platform_device 
*pdev)
reset_control_assert(phy->apb_rst);
pm_runtime_disable(>dev);
 
+   cdns_sierra_phy_disable_clocks(phy);
/*
 * The device level resets will be put automatically.
 * Need to put the subnode resets here though.
@@ -950,7 +985,6 @@ static int cdns_sierra_phy_remove(struct platform_device 
*pdev)
reset_control_put(phy->phys[i].lnk_rst);
}
 
-   clk_disable_unprepare(phy->input_clks[PHY_CLK]);
cdns_sierra_clk_unregister(phy);
 
return 0;
-- 
2.17.1



Re: [PATCH v6 3/3] arm64: dts: ti: k3-j7200: Add support for higher speed modes and update delay select values for MMCSD subsystems

2021-03-18 Thread Kishon Vijay Abraham I
Hi Aswath,

On 19/03/21 9:14 am, Aswath Govindraju wrote:
> The following speed modes are now supported in J7200 SoC,
> - HS200 and HS400 modes at 1.8 V card voltage, in MMCSD0 subsystem [1].
> - UHS-I speed modes in MMCSD1 subsystem [1].
> 
> Add support for UHS-I modes by adding voltage regulator device tree nodes
> and corresponding pinmux details, to power cycle and voltage switch cards.
> Set respective tags in sdhci0 and remove no-1-8-v tag from sdhci1
> device tree nodes.
> 
> Also update the delay values for various speed modes supported, based on
> the revised january 2021 J7200 datasheet[2].
> 
> [1] - section 12.3.6.1.1 MMCSD Features, in
>   https://www.ti.com/lit/ug/spruiu1a/spruiu1a.pdf,
>   (SPRUIU1A – JULY 2020 – REVISED JANUARY 2021)
> 
> [2] - https://www.ti.com/lit/ds/symlink/dra821u.pdf,
>   (SPRSP57B – APRIL 2020 – REVISED JANUARY 2021)

Thanks for fixing the link.

Reviewed-by: Kishon Vijay Abraham I 
> 
> Signed-off-by: Aswath Govindraju 
> ---
>  .../dts/ti/k3-j7200-common-proc-board.dts | 42 +++
>  arch/arm64/boot/dts/ti/k3-j7200-main.dtsi | 14 ++-
>  2 files changed, 54 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts 
> b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts
> index b493f939b09a..6f90c3b1cf45 100644
> --- a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts
> +++ b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts
> @@ -16,6 +16,29 @@
>   stdout-path = "serial2:115200n8";
>   bootargs = "console=ttyS2,115200n8 
> earlycon=ns16550a,mmio32,0x0280";
>   };
> +
> + vdd_mmc1: fixedregulator-sd {
> + compatible = "regulator-fixed";
> + regulator-name = "vdd_mmc1";
> + regulator-min-microvolt = <330>;
> + regulator-max-microvolt = <330>;
> + regulator-boot-on;
> + enable-active-high;
> + gpios = < 2 GPIO_ACTIVE_HIGH>;
> + };
> +
> + vdd_sd_dv: gpio-regulator-vdd-sd-dv {
> + compatible = "regulator-gpio";
> + regulator-name = "vdd_sd_dv";
> + pinctrl-names = "default";
> + pinctrl-0 = <_sd_dv_pins_default>;
> + regulator-min-microvolt = <180>;
> + regulator-max-microvolt = <330>;
> + regulator-boot-on;
> + gpios = <_gpio0 55 GPIO_ACTIVE_HIGH>;
> + states = <180 0x0
> +   330 0x1>;
> + };
>  };
>  
>  _pmx0 {
> @@ -45,6 +68,13 @@
>  };
>  
>  _pmx0 {
> + main_i2c0_pins_default: main-i2c0-pins-default {
> + pinctrl-single,pins = <
> + J721E_IOPAD(0xd4, PIN_INPUT_PULLUP, 0) /* (V3) I2C0_SCL 
> */
> + J721E_IOPAD(0xd8, PIN_INPUT_PULLUP, 0) /* (W2) I2C0_SDA 
> */
> + >;
> + };
> +
>   main_i2c1_pins_default: main-i2c1-pins-default {
>   pinctrl-single,pins = <
>   J721E_IOPAD(0xdc, PIN_INPUT_PULLUP, 3) /* (U3) 
> ECAP0_IN_APWM_OUT.I2C1_SCL */
> @@ -70,6 +100,12 @@
>   J721E_IOPAD(0x120, PIN_OUTPUT, 0) /* (T4) USB0_DRVVBUS 
> */
>   >;
>   };
> +
> + vdd_sd_dv_pins_default: vdd_sd_dv_pins_default {
> + pinctrl-single,pins = <
> + J721E_IOPAD(0xd0, PIN_INPUT, 7) /* (T5) 
> SPI0_D1.GPIO0_55 */
> + >;
> + };
>  };
>  
>  _uart0 {
> @@ -157,6 +193,10 @@
>  };
>  
>  _i2c0 {
> + pinctrl-names = "default";
> + pinctrl-0 = <_i2c0_pins_default>;
> + clock-frequency = <40>;
> +
>   exp1: gpio@20 {
>   compatible = "ti,tca6416";
>   reg = <0x20>;
> @@ -206,6 +246,8 @@
>   /* SD card */
>   pinctrl-0 = <_mmc1_pins_default>;
>   pinctrl-names = "default";
> + vmmc-supply = <_mmc1>;
> + vqmmc-supply = <_sd_dv>;
>   ti,driver-strength-ohm = <50>;
>   disable-wp;
>  };
> diff --git a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi 
> b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi
> index e60650a62b14..f86c493a44f1 100644
> --- a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi
> +++ b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi
> @@ -512,11 +512,16 @@
>   ti,otap-del-sel-mmc-hs = <0x0>;
>   ti,otap-del-sel-ddr52 = <0x6>;
>   ti,otap-del-sel-hs200 = <0x8

Re: [PATCH v5 3/3] arm64: dts: ti: k3-j7200: Add support for higher speed modes and update delay select values for MMCSD subsystems

2021-03-18 Thread Kishon Vijay Abraham I
Hi,

On 10/03/21 9:49 pm, Aswath Govindraju wrote:
> The following speed modes are now supported in J7200 SoC,
> - HS200 and HS400 modes at 1.8 V card voltage, in MMCSD0 subsystem [1].
> - UHS-I speed modes in MMCSD1 subsystem [1].
> 
> Add support for UHS-I modes by adding voltage regulator device tree nodes
> and corresponding pinmux details, to power cycle and voltage switch cards.
> Set respective tags in sdhci0 and remove no-1-8-v tag from sdhci1
> device tree nodes.
> 
> Also update the delay values for various speed modes supported, based on
> the latest J7200 datasheet[2]

nit: Better to mention the datasheet version (as it's not latest anymore).
> 
> [1] - section 12.3.6.1.1 MMCSD Features, in
>   https://www.ti.com/lit/ug/spruiu1a/spruiu1a.pdf
> 
> [2] - https://www.ti.com/lit/ds/symlink/dra821a.pdf

Er.. this link is already broken.

Thanks
Kishon
> 
> Signed-off-by: Aswath Govindraju 
> ---
>  .../dts/ti/k3-j7200-common-proc-board.dts | 42 +++
>  arch/arm64/boot/dts/ti/k3-j7200-main.dtsi | 14 ++-
>  2 files changed, 54 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts 
> b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts
> index b493f939b09a..6f90c3b1cf45 100644
> --- a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts
> +++ b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts
> @@ -16,6 +16,29 @@
>   stdout-path = "serial2:115200n8";
>   bootargs = "console=ttyS2,115200n8 
> earlycon=ns16550a,mmio32,0x0280";
>   };
> +
> + vdd_mmc1: fixedregulator-sd {
> + compatible = "regulator-fixed";
> + regulator-name = "vdd_mmc1";
> + regulator-min-microvolt = <330>;
> + regulator-max-microvolt = <330>;
> + regulator-boot-on;
> + enable-active-high;
> + gpios = < 2 GPIO_ACTIVE_HIGH>;
> + };
> +
> + vdd_sd_dv: gpio-regulator-vdd-sd-dv {
> + compatible = "regulator-gpio";
> + regulator-name = "vdd_sd_dv";
> + pinctrl-names = "default";
> + pinctrl-0 = <_sd_dv_pins_default>;
> + regulator-min-microvolt = <180>;
> + regulator-max-microvolt = <330>;
> + regulator-boot-on;
> + gpios = <_gpio0 55 GPIO_ACTIVE_HIGH>;
> + states = <180 0x0
> +   330 0x1>;
> + };
>  };
>  
>  _pmx0 {
> @@ -45,6 +68,13 @@
>  };
>  
>  _pmx0 {
> + main_i2c0_pins_default: main-i2c0-pins-default {
> + pinctrl-single,pins = <
> + J721E_IOPAD(0xd4, PIN_INPUT_PULLUP, 0) /* (V3) I2C0_SCL 
> */
> + J721E_IOPAD(0xd8, PIN_INPUT_PULLUP, 0) /* (W2) I2C0_SDA 
> */
> + >;
> + };
> +
>   main_i2c1_pins_default: main-i2c1-pins-default {
>   pinctrl-single,pins = <
>   J721E_IOPAD(0xdc, PIN_INPUT_PULLUP, 3) /* (U3) 
> ECAP0_IN_APWM_OUT.I2C1_SCL */
> @@ -70,6 +100,12 @@
>   J721E_IOPAD(0x120, PIN_OUTPUT, 0) /* (T4) USB0_DRVVBUS 
> */
>   >;
>   };
> +
> + vdd_sd_dv_pins_default: vdd_sd_dv_pins_default {
> + pinctrl-single,pins = <
> + J721E_IOPAD(0xd0, PIN_INPUT, 7) /* (T5) 
> SPI0_D1.GPIO0_55 */
> + >;
> + };
>  };
>  
>  _uart0 {
> @@ -157,6 +193,10 @@
>  };
>  
>  _i2c0 {
> + pinctrl-names = "default";
> + pinctrl-0 = <_i2c0_pins_default>;
> + clock-frequency = <40>;
> +
>   exp1: gpio@20 {
>   compatible = "ti,tca6416";
>   reg = <0x20>;
> @@ -206,6 +246,8 @@
>   /* SD card */
>   pinctrl-0 = <_mmc1_pins_default>;
>   pinctrl-names = "default";
> + vmmc-supply = <_mmc1>;
> + vqmmc-supply = <_sd_dv>;
>   ti,driver-strength-ohm = <50>;
>   disable-wp;
>  };
> diff --git a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi 
> b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi
> index e60650a62b14..f86c493a44f1 100644
> --- a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi
> +++ b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi
> @@ -512,11 +512,16 @@
>   ti,otap-del-sel-mmc-hs = <0x0>;
>   ti,otap-del-sel-ddr52 = <0x6>;
>   ti,otap-del-sel-hs200 = <0x8>;
> - ti,otap-del-sel-hs400 = <0x0>;
> + ti,otap-del-sel-hs400 = <0x5>;
> + ti,itap-del-sel-legacy = <0x10>;
> + ti,itap-del-sel-mmc-hs = <0xa>;
>   ti,strobe-sel = <0x77>;
> + ti,clkbuf-sel = <0x7>;
>   ti,trm-icp = <0x8>;
>   bus-width = <8>;
>   mmc-ddr-1_8v;
> + mmc-hs200-1_8v;
> + mmc-hs400-1_8v;
>   dma-coherent;
>   };
>  
> @@ -534,7 +539,12 @@
>   ti,otap-del-sel-sdr50 = <0xc>;
>   ti,otap-del-sel-sdr104 = <0x5>;
>   ti,otap-del-sel-ddr50 = <0xc>;
> - 

Re: [PATCH v3 0/2] AM64: Add USB support

2021-03-17 Thread Kishon Vijay Abraham I
Aswath and Nishanth,

On 17/03/21 10:00 am, Aswath Govindraju wrote:
> The following series of patches, add USB support for AM642 evm.
> 
> USB test logs,
> https://pastebin.ubuntu.com/p/YSQRBWGmzd/

Vinod has provided stable tag [1]
git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy.git
tags/ti-serdes-for-5.13

This should unblock us from up-streaming SK along with this.

Thanks
Kishon

[1] -> http://lore.kernel.org/r/YFGjPNonIlA4Anar@vkoul-mobl.Dlink
> 
> Changes since v2:
> - dropped compatible string "ti,j721e-usb" leading to DT schema errors
> - Reran test logs
> - Couldn't pick up reviewed-by from kishon as a change was made in the
>   patch
> 
> Changes since v1:
> - Rebased the patches on top of ti-k3-dts-next
> - Added test logs
> 
> Aswath Govindraju (2):
>   arm64: dts: ti: k3-am64-main: Add DT node for USB subsystem
>   arm64: dts: ti: k3-am642-evm: Add USB support
> 
>  arch/arm64/boot/dts/ti/k3-am64-main.dtsi | 30 
>  arch/arm64/boot/dts/ti/k3-am642-evm.dts  | 18 ++
>  2 files changed, 48 insertions(+)
> 


Re: [PATCH v3 0/2] AM64: Add USB support

2021-03-17 Thread Kishon Vijay Abraham I
Hi,

On 17/03/21 8:22 pm, Kishon Vijay Abraham I wrote:
> Aswath and Nishanth,
> 
> On 17/03/21 10:00 am, Aswath Govindraju wrote:
>> The following series of patches, add USB support for AM642 evm.
>>
>> USB test logs,
>> https://pastebin.ubuntu.com/p/YSQRBWGmzd/
> 
> Vinod has provided stable tag [1]
> git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy.git
> tags/ti-serdes-for-5.13
> 
> This should unblock us from up-streaming SK along with this.

In case you prefer to send SK support as follow up patches

Reviewed-by: Kishon Vijay Abraham I 

Thanks
Kishon

> 
> Thanks
> Kishon
> 
> [1] -> http://lore.kernel.org/r/YFGjPNonIlA4Anar@vkoul-mobl.Dlink
>>
>> Changes since v2:
>> - dropped compatible string "ti,j721e-usb" leading to DT schema errors
>> - Reran test logs
>> - Couldn't pick up reviewed-by from kishon as a change was made in the
>>   patch
>>
>> Changes since v1:
>> - Rebased the patches on top of ti-k3-dts-next
>> - Added test logs
>>
>> Aswath Govindraju (2):
>>   arm64: dts: ti: k3-am64-main: Add DT node for USB subsystem
>>   arm64: dts: ti: k3-am642-evm: Add USB support
>>
>>  arch/arm64/boot/dts/ti/k3-am64-main.dtsi | 30 
>>  arch/arm64/boot/dts/ti/k3-am642-evm.dts  | 18 ++
>>  2 files changed, 48 insertions(+)
>>


[PATCH] PCI: keystone: Let AM65 use the pci_ops defined in pcie-designware-host.c

2021-03-17 Thread Kishon Vijay Abraham I
Both TI's AM65x (K3) and TI's K2 PCIe driver are implemented in
pci-keystone. However Only K2 PCIe driver should use it's own pci_ops
for configuration space accesses. But commit 10a797c6e54a
("PCI: dwc: keystone: Use pci_ops for config space accessors") used
custom pci_ops for both AM65x and K2. This breaks configuration space
access for AM65x platform. Fix it here.

Fixes: 10a797c6e54a ("PCI: dwc: keystone: Use pci_ops for config space 
accessors")
Signed-off-by: Kishon Vijay Abraham I 
Cc:  # v5.10
---
 drivers/pci/controller/dwc/pci-keystone.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c 
b/drivers/pci/controller/dwc/pci-keystone.c
index 53aa35cb3a49..a59ecbec601f 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -798,7 +798,8 @@ static int __init ks_pcie_host_init(struct pcie_port *pp)
int ret;
 
pp->bridge->ops = _pcie_ops;
-   pp->bridge->child_ops = _child_pcie_ops;
+   if (!ks_pcie->is_am6)
+   pp->bridge->child_ops = _child_pcie_ops;
 
ret = ks_pcie_config_legacy_irq(ks_pcie);
if (ret)
-- 
2.17.1



Re: [PATCH] dt-bindings: Clean-up undocumented compatible strings

2021-03-16 Thread Kishon Vijay Abraham I



On 17/03/21 1:19 am, Rob Herring wrote:
> Adding checks for undocumented compatible strings reveals a bunch of
> warnings in the DT binding examples. Fix the cases which are typos, just
> a mismatch between the schema and the example, or aren't documented at all.
> In a couple of cases, fixing the compatible revealed some schema errors
> which are fixed.
> 
> There's a bunch of others remaining after this which have bindings, but
> those aren't converted to schema yet.
> 
> Cc: Stephen Boyd 
> Cc: Maxime Ripard 
> Cc: Thierry Reding 
> Cc: Sam Ravnborg 
> Cc: Vinod Koul 
> Cc: Alexandre Belloni 
> Cc: Jonathan Cameron 
> Cc: Pavel Machek 
> Cc: Kishon Vijay Abraham I 
> Cc: Sebastian Reichel 
> Cc: Mark Brown 
> Cc: Greg Kroah-Hartman 
> Cc: linux-...@vger.kernel.org
> Cc: dmaeng...@vger.kernel.org
> Cc: linux-...@lists.infradead.org
> Cc: linux-...@vger.kernel.org
> Cc: linux-l...@vger.kernel.org
> Cc: linux...@vger.kernel.org
> Cc: linux-ser...@vger.kernel.org
> Cc: linux-...@vger.kernel.org
> Signed-off-by: Rob Herring 

Acked-by: Kishon Vijay Abraham I 

> ---
>  .../clock/allwinner,sun4i-a10-pll1-clk.yaml   |  2 +-
>  .../bindings/clock/milbeaut-clock.yaml| 12 +
>  .../bindings/display/brcm,bcm2835-dsi0.yaml   |  6 -
>  .../bindings/display/panel/panel-dpi.yaml |  2 +-
>  .../devicetree/bindings/dma/qcom,gpi.yaml |  2 +-
>  .../devicetree/bindings/i3c/i3c.yaml  |  7 ++---
>  .../iio/adc/brcm,iproc-static-adc.yaml|  5 
>  .../iio/gyroscope/nxp,fxas21002c.yaml |  2 +-
>  .../bindings/iio/light/upisemi,us5182.yaml|  4 +--
>  .../interrupt-controller/loongson,htpic.yaml  |  2 +-
>  .../devicetree/bindings/leds/leds-lgm.yaml| 26 ---
>  .../bindings/phy/ti,phy-j721e-wiz.yaml|  2 +-
>  .../bindings/power/supply/cw2015_battery.yaml |  2 +-
>  .../bindings/power/supply/power-supply.yaml   | 22 
>  .../devicetree/bindings/serial/serial.yaml|  2 +-
>  .../bindings/spi/amlogic,meson-gx-spicc.yaml  |  4 +--
>  .../bindings/spi/spi-controller.yaml  | 21 ---
>  .../devicetree/bindings/spi/spi-mux.yaml  |  8 ++
>  .../devicetree/bindings/spi/st,stm32-spi.yaml |  6 -
>  19 files changed, 58 insertions(+), 79 deletions(-)
> 
> diff --git 
> a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-pll1-clk.yaml 
> b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-pll1-clk.yaml
> index e9c4cf834aa7..e5d9d45dab8a 100644
> --- 
> a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-pll1-clk.yaml
> +++ 
> b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-pll1-clk.yaml
> @@ -44,7 +44,7 @@ examples:
>- |
>  clk@1c2 {
>  #clock-cells = <0>;
> -compatible = "allwinner,sun4i-a10-pll1";
> +compatible = "allwinner,sun4i-a10-pll1-clk";
>  reg = <0x01c2 0x4>;
>  clocks = <>;
>  clock-output-names = "osc24M";
> diff --git a/Documentation/devicetree/bindings/clock/milbeaut-clock.yaml 
> b/Documentation/devicetree/bindings/clock/milbeaut-clock.yaml
> index 0e8b07710451..6d39344d2b70 100644
> --- a/Documentation/devicetree/bindings/clock/milbeaut-clock.yaml
> +++ b/Documentation/devicetree/bindings/clock/milbeaut-clock.yaml
> @@ -18,10 +18,12 @@ description: |
>  
>  properties:
>compatible:
> -oneOf:
> -  - items:
> -  - enum:
> -  - socionext,milbeaut-m10v-ccu
> +enum:
> +  - socionext,milbeaut-m10v-ccu
> +
> +  reg:
> +maxItems: 1
> +
>clocks:
>  maxItems: 1
>  description: external clock
> @@ -41,7 +43,7 @@ examples:
># Clock controller node:
>- |
>  m10v-clk-ctrl@1d021000 {
> -compatible = "socionext,milbeaut-m10v-clk-ccu";
> +compatible = "socionext,milbeaut-m10v-ccu";
>  reg = <0x1d021000 0x4000>;
>  #clock-cells = <1>;
>  clocks = <>;
> diff --git a/Documentation/devicetree/bindings/display/brcm,bcm2835-dsi0.yaml 
> b/Documentation/devicetree/bindings/display/brcm,bcm2835-dsi0.yaml
> index 55c60919991f..32608578a352 100644
> --- a/Documentation/devicetree/bindings/display/brcm,bcm2835-dsi0.yaml
> +++ b/Documentation/devicetree/bindings/display/brcm,bcm2835-dsi0.yaml
> @@ -77,12 +77,6 @@ examples:
>  
>  clock-output-names = "dsi1_byte", "dsi1_ddr2", "dsi1_ddr";
>  
> -pitouchscreen: panel@0 {
> -compatible = "raspberrypi,touchscreen";
> -reg = <0>;
> -
> -/* ... 

Re: [PATCH 0/3] AM64: Add SERDES DT bindings

2021-03-16 Thread Kishon Vijay Abraham I
Hi Vinod,

On 10/03/21 4:57 pm, Kishon Vijay Abraham I wrote:
> Patch series adds device tree bindings to support SERDES in AM64
> platform.
> 
> This is split from [1] since this binding is also required for AM64
> USB DT patches to be merged.
> 
> Vinod,
> 
> Once the 1st patch of the series is reviewed by Rob, can you merge and
> prepare a immutable tag to be used by Nishant Menon so that he can merge
> USB3 DT patches.

Now that Rob has Acked the 1st patch, can you prepare an immutable tag
for Nishant Menon on this series.

AM64 SERDES driver changes [1] can also be merged after this.

Thank You
Kishon

[1] -> http://lore.kernel.org/r/20210310120840.16447-1-kis...@ti.com
> 
> Changes from [1]:
> *) Reverted back to adding compatible under enum.
> 
> [1] -> http://lore.kernel.org/r/20210222112314.10772-1-kis...@ti.com
> 
> Kishon Vijay Abraham I (3):
>   dt-bindings: phy: ti,phy-j721e-wiz: Add bindings for AM64 SERDES
> Wrapper
>   dt-bindings: phy: cadence-torrent: Add binding for refclk driver
>   dt-bindings: ti-serdes-mux: Add defines for AM64 SoC
> 
>  .../bindings/phy/phy-cadence-torrent.yaml | 20 +++---
>  .../bindings/phy/ti,phy-j721e-wiz.yaml|  4 
>  include/dt-bindings/mux/ti-serdes.h   |  5 +
>  include/dt-bindings/phy/phy-cadence-torrent.h |  2 ++
>  include/dt-bindings/phy/phy-ti.h  | 21 +++
>  5 files changed, 49 insertions(+), 3 deletions(-)
>  create mode 100644 include/dt-bindings/phy/phy-ti.h
> 


Re: [PATCH v15 2/4] phy: Add media type and speed serdes configuration interfaces

2021-03-16 Thread Kishon Vijay Abraham I



On 18/02/21 9:44 pm, Steen Hegelund wrote:
> Provide new phy configuration interfaces for media type and speed that
> allows e.g. PHYs used for ethernet to be configured with this
> information.
> 
> Signed-off-by: Lars Povlsen 
> Signed-off-by: Steen Hegelund 
> Reviewed-by: Andrew Lunn 
> Reviewed-by: Alexandre Belloni 

Acked-By: Kishon Vijay Abraham I 
> ---
>  drivers/phy/phy-core.c  | 30 ++
>  include/linux/phy/phy.h | 26 ++
>  2 files changed, 56 insertions(+)
> 
> diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
> index 71cb10826326..ccb575b13777 100644
> --- a/drivers/phy/phy-core.c
> +++ b/drivers/phy/phy-core.c
> @@ -373,6 +373,36 @@ int phy_set_mode_ext(struct phy *phy, enum phy_mode 
> mode, int submode)
>  }
>  EXPORT_SYMBOL_GPL(phy_set_mode_ext);
>  
> +int phy_set_media(struct phy *phy, enum phy_media media)
> +{
> + int ret;
> +
> + if (!phy || !phy->ops->set_media)
> + return 0;
> +
> + mutex_lock(>mutex);
> + ret = phy->ops->set_media(phy, media);
> + mutex_unlock(>mutex);
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(phy_set_media);
> +
> +int phy_set_speed(struct phy *phy, int speed)
> +{
> + int ret;
> +
> + if (!phy || !phy->ops->set_speed)
> + return 0;
> +
> + mutex_lock(>mutex);
> + ret = phy->ops->set_speed(phy, speed);
> + mutex_unlock(>mutex);
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(phy_set_speed);
> +
>  int phy_reset(struct phy *phy)
>  {
>   int ret;
> diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
> index e435bdb0bab3..0ed434d02196 100644
> --- a/include/linux/phy/phy.h
> +++ b/include/linux/phy/phy.h
> @@ -44,6 +44,12 @@ enum phy_mode {
>   PHY_MODE_DP
>  };
>  
> +enum phy_media {
> + PHY_MEDIA_DEFAULT,
> + PHY_MEDIA_SR,
> + PHY_MEDIA_DAC,
> +};
> +
>  /**
>   * union phy_configure_opts - Opaque generic phy configuration
>   *
> @@ -64,6 +70,8 @@ union phy_configure_opts {
>   * @power_on: powering on the phy
>   * @power_off: powering off the phy
>   * @set_mode: set the mode of the phy
> + * @set_media: set the media type of the phy (optional)
> + * @set_speed: set the speed of the phy (optional)
>   * @reset: resetting the phy
>   * @calibrate: calibrate the phy
>   * @release: ops to be performed while the consumer relinquishes the PHY
> @@ -75,6 +83,8 @@ struct phy_ops {
>   int (*power_on)(struct phy *phy);
>   int (*power_off)(struct phy *phy);
>   int (*set_mode)(struct phy *phy, enum phy_mode mode, int submode);
> + int (*set_media)(struct phy *phy, enum phy_media media);
> + int (*set_speed)(struct phy *phy, int speed);
>  
>   /**
>* @configure:
> @@ -215,6 +225,8 @@ int phy_power_off(struct phy *phy);
>  int phy_set_mode_ext(struct phy *phy, enum phy_mode mode, int submode);
>  #define phy_set_mode(phy, mode) \
>   phy_set_mode_ext(phy, mode, 0)
> +int phy_set_media(struct phy *phy, enum phy_media media);
> +int phy_set_speed(struct phy *phy, int speed);
>  int phy_configure(struct phy *phy, union phy_configure_opts *opts);
>  int phy_validate(struct phy *phy, enum phy_mode mode, int submode,
>union phy_configure_opts *opts);
> @@ -344,6 +356,20 @@ static inline int phy_set_mode_ext(struct phy *phy, enum 
> phy_mode mode,
>  #define phy_set_mode(phy, mode) \
>   phy_set_mode_ext(phy, mode, 0)
>  
> +static inline int phy_set_media(struct phy *phy, enum phy_media media)
> +{
> + if (!phy)
> + return 0;
> + return -ENODEV;
> +}
> +
> +static inline int phy_set_speed(struct phy *phy, int speed)
> +{
> + if (!phy)
> + return 0;
> + return -ENODEV;
> +}
> +
>  static inline enum phy_mode phy_get_mode(struct phy *phy)
>  {
>   return PHY_MODE_INVALID;
> 


Re: [PATCH 2/2] PCI: cadence: Set LTSSM Detect.Quiet state delay.

2021-03-15 Thread Kishon Vijay Abraham I
Hi Nadeem,

On 09/03/21 1:01 pm, Nadeem Athani wrote:
> The parameter detect_quiet_min_delay can be used to program the minimum
> time that LTSSM waits on entering Detect.Quiet state.
> 00 : 0us minimum wait time in Detect.Quiet state.
> 01 : 100us minimum wait time in Detect.Quiet state.
> 10 : 1000us minimum wait time in Detect.Quiet state.
> 11 : 2000us minimum wait time in Detect.Quiet state.
> 
> As per PCIe specification, all Receivers must meet the Z-RX-DC
> specification for 2.5 GT/s within 1000us of entering Detect.Quiet LTSSM
> substate. The LTSSM must stay in this substate until the ZRXDC
> specification for 2.5 GT/s is met.
> 
> Signed-off-by: Nadeem Athani 
> ---
>  drivers/pci/controller/cadence/pcie-cadence-host.c | 22 
> ++
>  drivers/pci/controller/cadence/pcie-cadence.h  | 10 ++
>  2 files changed, 32 insertions(+)
> 
> diff --git a/drivers/pci/controller/cadence/pcie-cadence-host.c 
> b/drivers/pci/controller/cadence/pcie-cadence-host.c
> index 73dcf8cf98fb..056161b3fe65 100644
> --- a/drivers/pci/controller/cadence/pcie-cadence-host.c
> +++ b/drivers/pci/controller/cadence/pcie-cadence-host.c
> @@ -461,6 +461,20 @@ static int cdns_pcie_host_init(struct device *dev,
>   return cdns_pcie_host_init_address_translation(rc);
>  }
>  
> +static void cdns_pcie_detect_quiet_min_delay_set(struct cdns_pcie_rc *rc)
> +{
> + struct cdns_pcie *pcie = >pcie;
> + u32 delay = rc->detect_quiet_min_delay;
> + u32 ltssm_control_cap;
> +
> + ltssm_control_cap = cdns_pcie_readl(pcie, CDNS_PCIE_LTSSM_CONTROL_CAP);
> + ltssm_control_cap = ((ltssm_control_cap &
> +  ~CDNS_PCIE_DETECT_QUIET_MIN_DELAY_MASK) |
> + CDNS_PCIE_DETECT_QUIET_MIN_DELAY(delay));
> +
> + cdns_pcie_writel(pcie, CDNS_PCIE_LTSSM_CONTROL_CAP, ltssm_control_cap);
> +}
> +

The issue is not specific to only host mode.

Thanks
Kishon
>  int cdns_pcie_host_setup(struct cdns_pcie_rc *rc)
>  {
>   struct device *dev = rc->pcie.dev;
> @@ -485,6 +499,10 @@ int cdns_pcie_host_setup(struct cdns_pcie_rc *rc)
>   rc->device_id = 0x;
>   of_property_read_u32(np, "device-id", >device_id);
>  
> + rc->detect_quiet_min_delay = 0;
> + of_property_read_u32(np, "detect-quiet-min-delay",
> +  >detect_quiet_min_delay);
> +
>   pcie->reg_base = devm_platform_ioremap_resource_byname(pdev, "reg");
>   if (IS_ERR(pcie->reg_base)) {
>   dev_err(dev, "missing \"reg\"\n");
> @@ -497,6 +515,10 @@ int cdns_pcie_host_setup(struct cdns_pcie_rc *rc)
>   return PTR_ERR(rc->cfg_base);
>   rc->cfg_res = res;
>  
> + /* Default Detect.Quiet state delay is 0 */
> + if (rc->detect_quiet_min_delay)
> + cdns_pcie_detect_quiet_min_delay_set(rc);
> +
>   ret = cdns_pcie_start_link(pcie);
>   if (ret) {
>   dev_err(dev, "Failed to start link\n");
> diff --git a/drivers/pci/controller/cadence/pcie-cadence.h 
> b/drivers/pci/controller/cadence/pcie-cadence.h
> index 254d2570f8c9..f2d3cca2c707 100644
> --- a/drivers/pci/controller/cadence/pcie-cadence.h
> +++ b/drivers/pci/controller/cadence/pcie-cadence.h
> @@ -189,6 +189,14 @@
>  /* AXI link down register */
>  #define CDNS_PCIE_AT_LINKDOWN (CDNS_PCIE_AT_BASE + 0x0824)
>  
> +/* LTSSM Capabilities register */
> +#define CDNS_PCIE_LTSSM_CONTROL_CAP   (CDNS_PCIE_LM_BASE + 0x0054)
> +#define  CDNS_PCIE_DETECT_QUIET_MIN_DELAY_MASKGENMASK(2, 1)
> +#define  CDNS_PCIE_DETECT_QUIET_MIN_DELAY_SHIFT 1
> +#define  CDNS_PCIE_DETECT_QUIET_MIN_DELAY(delay) \
> +   (((delay) << CDNS_PCIE_DETECT_QUIET_MIN_DELAY_SHIFT) & \
> +   CDNS_PCIE_DETECT_QUIET_MIN_DELAY_MASK)
> +
>  enum cdns_pcie_rp_bar {
>   RP_BAR_UNDEFINED = -1,
>   RP_BAR0,
> @@ -289,6 +297,7 @@ struct cdns_pcie {
>   *single function at a time
>   * @vendor_id: PCI vendor ID
>   * @device_id: PCI device ID
> + * @detect_quiet_min_delay: LTSSM Detect Quite state min. delay
>   * @avail_ib_bar: Satus of RP_BAR0, RP_BAR1 and  RP_NO_BAR if it's free 
> or
>   *available
>   * @quirk_retrain_flag: Retrain link as quirk for PCIe Gen2
> @@ -299,6 +308,7 @@ struct cdns_pcie_rc {
>   void __iomem*cfg_base;
>   u32 vendor_id;
>   u32 device_id;
> + u32 detect_quiet_min_delay;
>   boolavail_ib_bar[CDNS_PCIE_RP_MAX_IB];
>   boolquirk_retrain_flag;
>  };
> 


Re: [PATCH v2 0/2] AM64: Add USB support

2021-03-14 Thread Kishon Vijay Abraham I



On 10/03/21 4:57 pm, Aswath Govindraju wrote:
> The following series of patches, add USB support for AM642 evm.
> 
> USB test logs,
> https://pastebin.ubuntu.com/p/Qrbb7SGv8N/
> 
> Changes since v1:
> - Rebased the patches on top of ti-k3-dts-next
> - Added test logs

Would prefer simple data transfer tests in the log but other than that
for the patches itself

Reviewed-by: Kishon Vijay Abraham I 
> 
> Aswath Govindraju (2):
>   arm64: dts: ti: k3-am64-main: Add DT node for USB subsystem
>   arm64: dts: ti: k3-am642-evm: Add USB support
> 
>  arch/arm64/boot/dts/ti/k3-am64-main.dtsi | 30 
>  arch/arm64/boot/dts/ti/k3-am642-evm.dts  | 18 ++
>  2 files changed, 48 insertions(+)
> 


[PATCH v4 7/7] Documentation: PCI: endpoint/pci-endpoint-cfs: Guide to use SR-IOV

2021-03-10 Thread Kishon Vijay Abraham I
Add Documentation to help users use PCI endpoint to create virtual
functions using configfs. An endpoint function is designated as a
virtual endpoint function device when it is linked to a physical
endpoint function device (instead of a endpoint controller).

Signed-off-by: Kishon Vijay Abraham I 
---
 Documentation/PCI/endpoint/pci-endpoint-cfs.rst | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/Documentation/PCI/endpoint/pci-endpoint-cfs.rst 
b/Documentation/PCI/endpoint/pci-endpoint-cfs.rst
index 696f8eeb4738..56fb33c5e8fd 100644
--- a/Documentation/PCI/endpoint/pci-endpoint-cfs.rst
+++ b/Documentation/PCI/endpoint/pci-endpoint-cfs.rst
@@ -43,6 +43,7 @@ entries corresponding to EPF driver will be created by the 
EPF core.
.. /
... /
... /
+   ... /
.. /
... /
... /
@@ -68,6 +69,7 @@ created)
... subsys_vendor_id
... subsys_id
... interrupt_pin
+   ... /
 ... primary/
... /
 ... secondary/
@@ -79,6 +81,13 @@ interface should be added in 'primary' directory and symlink 
of endpoint
 controller connected to secondary interface should be added in 'secondary'
 directory.
 
+The  directory can have a list of symbolic links
+() to other . These symbolic links should
+be created by the user to represent the virtual functions that are bound to
+the physical function. In the above directory structure  is a
+physical function and  is a virtual function. An EPF device once
+it's linked to another EPF device, cannot be linked to a EPC device.
+
 EPC Device
 ==
 
@@ -98,7 +107,8 @@ entries corresponding to EPC device will be created by the 
EPC core.
 
 The  directory will have a list of symbolic links to
 . These symbolic links should be created by the user to
-represent the functions present in the endpoint device.
+represent the functions present in the endpoint device. Only 
+that represents a physical function can be linked to a EPC device.
 
 The  directory will also have a *start* field. Once
 "1" is written to this field, the endpoint device will be ready to
-- 
2.17.1



[PATCH v4 6/7] misc: pci_endpoint_test: Populate sriov_configure ops to configure SR-IOV device

2021-03-10 Thread Kishon Vijay Abraham I
Populate sriov_configure ops with pci_sriov_configure_simple to
configure SR-IOV device.

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/misc/pci_endpoint_test.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c
index 1b2868ca4f2a..c7ee34013485 100644
--- a/drivers/misc/pci_endpoint_test.c
+++ b/drivers/misc/pci_endpoint_test.c
@@ -978,6 +978,7 @@ static struct pci_driver pci_endpoint_test_driver = {
.id_table   = pci_endpoint_test_tbl,
.probe  = pci_endpoint_test_probe,
.remove = pci_endpoint_test_remove,
+   .sriov_configure = pci_sriov_configure_simple,
 };
 module_pci_driver(pci_endpoint_test_driver);
 
-- 
2.17.1



[PATCH v4 5/7] PCI: cadence: Add support to configure virtual functions

2021-03-10 Thread Kishon Vijay Abraham I
Now that support for SR-IOV is added in PCIe endpoint core, add support
to configure virtual functions in the Cadence PCIe EP driver.

Signed-off-by: Kishon Vijay Abraham I 
---
 .../pci/controller/cadence/pcie-cadence-ep.c  | 207 --
 drivers/pci/controller/cadence/pcie-cadence.h |   7 +
 2 files changed, 197 insertions(+), 17 deletions(-)

diff --git a/drivers/pci/controller/cadence/pcie-cadence-ep.c 
b/drivers/pci/controller/cadence/pcie-cadence-ep.c
index 912a15be8bfd..0bbff57c5787 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-ep.c
+++ b/drivers/pci/controller/cadence/pcie-cadence-ep.c
@@ -20,7 +20,18 @@ static int cdns_pcie_ep_write_header(struct pci_epc *epc, u8 
fn, u8 vfn,
 struct pci_epf_header *hdr)
 {
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
+   u32 cap = CDNS_PCIE_EP_FUNC_SRIOV_CAP_OFFSET;
struct cdns_pcie *pcie = >pcie;
+   u32 reg;
+
+   if (vfn > 1) {
+   dev_dbg(>dev, "Only Virtual Function #1 has deviceID\n");
+   return 0;
+   } else if (vfn == 1) {
+   reg = cap + PCI_SRIOV_VF_DID;
+   cdns_pcie_ep_fn_writew(pcie, fn, reg, hdr->deviceid);
+   return 0;
+   }
 
cdns_pcie_ep_fn_writew(pcie, fn, PCI_DEVICE_ID, hdr->deviceid);
cdns_pcie_ep_fn_writeb(pcie, fn, PCI_REVISION_ID, hdr->revid);
@@ -51,12 +62,14 @@ static int cdns_pcie_ep_set_bar(struct pci_epc *epc, u8 fn, 
u8 vfn,
struct pci_epf_bar *epf_bar)
 {
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
+   u32 cap = CDNS_PCIE_EP_FUNC_SRIOV_CAP_OFFSET;
struct cdns_pcie_epf *epf = >epf[fn];
struct cdns_pcie *pcie = >pcie;
dma_addr_t bar_phys = epf_bar->phys_addr;
enum pci_barno bar = epf_bar->barno;
int flags = epf_bar->flags;
u32 addr0, addr1, reg, cfg, b, aperture, ctrl;
+   u32 first_vf_offset, stride;
u64 sz;
 
/* BAR size is 2^(aperture + 7) */
@@ -92,19 +105,39 @@ static int cdns_pcie_ep_set_bar(struct pci_epc *epc, u8 
fn, u8 vfn,
 
addr0 = lower_32_bits(bar_phys);
addr1 = upper_32_bits(bar_phys);
+
+   if (vfn == 1) {
+   if (bar < BAR_4) {
+   reg = CDNS_PCIE_LM_EP_VFUNC_BAR_CFG0(fn);
+   b = bar;
+   } else {
+   reg = CDNS_PCIE_LM_EP_VFUNC_BAR_CFG1(fn);
+   b = bar - BAR_4;
+   }
+   } else {
+   if (bar < BAR_4) {
+   reg = CDNS_PCIE_LM_EP_FUNC_BAR_CFG0(fn);
+   b = bar;
+   } else {
+   reg = CDNS_PCIE_LM_EP_FUNC_BAR_CFG1(fn);
+   b = bar - BAR_4;
+   }
+   }
+
+   if (vfn > 0) {
+   first_vf_offset = cdns_pcie_ep_fn_readw(pcie, fn, cap +
+   PCI_SRIOV_VF_OFFSET);
+   stride = cdns_pcie_ep_fn_readw(pcie, fn, cap +
+  PCI_SRIOV_VF_STRIDE);
+   fn = fn + first_vf_offset + ((vfn - 1) * stride);
+   epf = >epf[vfn - 1];
+   }
+
cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_EP_FUNC_BAR_ADDR0(fn, bar),
 addr0);
cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar),
 addr1);
 
-   if (bar < BAR_4) {
-   reg = CDNS_PCIE_LM_EP_FUNC_BAR_CFG0(fn);
-   b = bar;
-   } else {
-   reg = CDNS_PCIE_LM_EP_FUNC_BAR_CFG1(fn);
-   b = bar - BAR_4;
-   }
-
cfg = cdns_pcie_readl(pcie, reg);
cfg &= ~(CDNS_PCIE_LM_EP_FUNC_BAR_CFG_BAR_APERTURE_MASK(b) |
 CDNS_PCIE_LM_EP_FUNC_BAR_CFG_BAR_CTRL_MASK(b));
@@ -121,17 +154,38 @@ static void cdns_pcie_ep_clear_bar(struct pci_epc *epc, 
u8 fn, u8 vfn,
   struct pci_epf_bar *epf_bar)
 {
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
+   u32 cap = CDNS_PCIE_EP_FUNC_SRIOV_CAP_OFFSET;
struct cdns_pcie_epf *epf = >epf[fn];
struct cdns_pcie *pcie = >pcie;
enum pci_barno bar = epf_bar->barno;
+   u32 first_vf_offset, stride;
u32 reg, cfg, b, ctrl;
 
-   if (bar < BAR_4) {
-   reg = CDNS_PCIE_LM_EP_FUNC_BAR_CFG0(fn);
-   b = bar;
+   if (vfn == 1) {
+   if (bar < BAR_4) {
+   reg = CDNS_PCIE_LM_EP_VFUNC_BAR_CFG0(fn);
+   b = bar;
+   } else {
+   reg = CDNS_PCIE_LM_EP_VFUNC_BAR_CFG1(fn);
+   b = bar - BAR_4;
+   }
} else {
-   reg = CDNS_PCIE_LM_EP_FUNC_BAR_CFG1(fn);
-   b = bar - BAR_4;
+   if (bar < BAR_4) {
+ 

[PATCH v4 3/7] PCI: endpoint: Add support to link a physical function to a virtual function

2021-03-10 Thread Kishon Vijay Abraham I
While the physical function has to be linked to endpoint controller, the
virtual function has to be linked to a physical function. Add support to
link a physical function to a virtual function in pci-ep-cfs.

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/pci/endpoint/pci-ep-cfs.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/drivers/pci/endpoint/pci-ep-cfs.c 
b/drivers/pci/endpoint/pci-ep-cfs.c
index f3a8b833b479..11801877 100644
--- a/drivers/pci/endpoint/pci-ep-cfs.c
+++ b/drivers/pci/endpoint/pci-ep-cfs.c
@@ -475,6 +475,28 @@ static struct configfs_attribute *pci_epf_attrs[] = {
NULL,
 };
 
+static int pci_epf_vepf_link(struct config_item *epf_pf_item,
+struct config_item *epf_vf_item)
+{
+   struct pci_epf_group *epf_vf_group = to_pci_epf_group(epf_vf_item);
+   struct pci_epf_group *epf_pf_group = to_pci_epf_group(epf_pf_item);
+   struct pci_epf *epf_pf = epf_pf_group->epf;
+   struct pci_epf *epf_vf = epf_vf_group->epf;
+
+   return pci_epf_add_vepf(epf_pf, epf_vf);
+}
+
+static void pci_epf_vepf_unlink(struct config_item *epf_pf_item,
+   struct config_item *epf_vf_item)
+{
+   struct pci_epf_group *epf_vf_group = to_pci_epf_group(epf_vf_item);
+   struct pci_epf_group *epf_pf_group = to_pci_epf_group(epf_pf_item);
+   struct pci_epf *epf_pf = epf_pf_group->epf;
+   struct pci_epf *epf_vf = epf_vf_group->epf;
+
+   pci_epf_remove_vepf(epf_pf, epf_vf);
+}
+
 static void pci_epf_release(struct config_item *item)
 {
struct pci_epf_group *epf_group = to_pci_epf_group(item);
@@ -487,6 +509,8 @@ static void pci_epf_release(struct config_item *item)
 }
 
 static struct configfs_item_operations pci_epf_ops = {
+   .allow_link = pci_epf_vepf_link,
+   .drop_link  = pci_epf_vepf_unlink,
.release= pci_epf_release,
 };
 
-- 
2.17.1



[PATCH v4 4/7] PCI: endpoint: Add virtual function number in pci_epc ops

2021-03-10 Thread Kishon Vijay Abraham I
Add virtual function number in pci_epc ops. EPC controller driver
can perform virtual function specific initialization based on the
virtual function number.

Signed-off-by: Kishon Vijay Abraham I 
---
 .../pci/controller/cadence/pcie-cadence-ep.c  |  44 +++---
 .../pci/controller/dwc/pcie-designware-ep.c   |  36 ++---
 drivers/pci/controller/pcie-rcar-ep.c |  19 +--
 drivers/pci/controller/pcie-rockchip-ep.c |  18 +--
 drivers/pci/endpoint/functions/pci-epf-ntb.c  |  79 ++-
 drivers/pci/endpoint/functions/pci-epf-test.c |  66 +
 drivers/pci/endpoint/pci-epc-core.c   | 128 --
 drivers/pci/endpoint/pci-epf-core.c   |  48 ++-
 include/linux/pci-epc.h   |  57 
 9 files changed, 313 insertions(+), 182 deletions(-)

diff --git a/drivers/pci/controller/cadence/pcie-cadence-ep.c 
b/drivers/pci/controller/cadence/pcie-cadence-ep.c
index 897cdde02bd8..912a15be8bfd 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-ep.c
+++ b/drivers/pci/controller/cadence/pcie-cadence-ep.c
@@ -16,7 +16,7 @@
 #define CDNS_PCIE_EP_IRQ_PCI_ADDR_NONE 0x1
 #define CDNS_PCIE_EP_IRQ_PCI_ADDR_LEGACY   0x3
 
-static int cdns_pcie_ep_write_header(struct pci_epc *epc, u8 fn,
+static int cdns_pcie_ep_write_header(struct pci_epc *epc, u8 fn, u8 vfn,
 struct pci_epf_header *hdr)
 {
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
@@ -47,7 +47,7 @@ static int cdns_pcie_ep_write_header(struct pci_epc *epc, u8 
fn,
return 0;
 }
 
-static int cdns_pcie_ep_set_bar(struct pci_epc *epc, u8 fn,
+static int cdns_pcie_ep_set_bar(struct pci_epc *epc, u8 fn, u8 vfn,
struct pci_epf_bar *epf_bar)
 {
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
@@ -117,7 +117,7 @@ static int cdns_pcie_ep_set_bar(struct pci_epc *epc, u8 fn,
return 0;
 }
 
-static void cdns_pcie_ep_clear_bar(struct pci_epc *epc, u8 fn,
+static void cdns_pcie_ep_clear_bar(struct pci_epc *epc, u8 fn, u8 vfn,
   struct pci_epf_bar *epf_bar)
 {
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
@@ -147,8 +147,8 @@ static void cdns_pcie_ep_clear_bar(struct pci_epc *epc, u8 
fn,
epf->epf_bar[bar] = NULL;
 }
 
-static int cdns_pcie_ep_map_addr(struct pci_epc *epc, u8 fn, phys_addr_t addr,
-u64 pci_addr, size_t size)
+static int cdns_pcie_ep_map_addr(struct pci_epc *epc, u8 fn, u8 vfn,
+phys_addr_t addr, u64 pci_addr, size_t size)
 {
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
struct cdns_pcie *pcie = >pcie;
@@ -169,7 +169,7 @@ static int cdns_pcie_ep_map_addr(struct pci_epc *epc, u8 
fn, phys_addr_t addr,
return 0;
 }
 
-static void cdns_pcie_ep_unmap_addr(struct pci_epc *epc, u8 fn,
+static void cdns_pcie_ep_unmap_addr(struct pci_epc *epc, u8 fn, u8 vfn,
phys_addr_t addr)
 {
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
@@ -189,7 +189,7 @@ static void cdns_pcie_ep_unmap_addr(struct pci_epc *epc, u8 
fn,
clear_bit(r, >ob_region_map);
 }
 
-static int cdns_pcie_ep_set_msi(struct pci_epc *epc, u8 fn, u8 mmc)
+static int cdns_pcie_ep_set_msi(struct pci_epc *epc, u8 fn, u8 vfn, u8 mmc)
 {
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
struct cdns_pcie *pcie = >pcie;
@@ -209,7 +209,7 @@ static int cdns_pcie_ep_set_msi(struct pci_epc *epc, u8 fn, 
u8 mmc)
return 0;
 }
 
-static int cdns_pcie_ep_get_msi(struct pci_epc *epc, u8 fn)
+static int cdns_pcie_ep_get_msi(struct pci_epc *epc, u8 fn, u8 vfn)
 {
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
struct cdns_pcie *pcie = >pcie;
@@ -230,7 +230,7 @@ static int cdns_pcie_ep_get_msi(struct pci_epc *epc, u8 fn)
return mme;
 }
 
-static int cdns_pcie_ep_get_msix(struct pci_epc *epc, u8 func_no)
+static int cdns_pcie_ep_get_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no)
 {
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
struct cdns_pcie *pcie = >pcie;
@@ -247,8 +247,9 @@ static int cdns_pcie_ep_get_msix(struct pci_epc *epc, u8 
func_no)
return val;
 }
 
-static int cdns_pcie_ep_set_msix(struct pci_epc *epc, u8 fn, u16 interrupts,
-enum pci_barno bir, u32 offset)
+static int cdns_pcie_ep_set_msix(struct pci_epc *epc, u8 fn, u8 vfn,
+u16 interrupts, enum pci_barno bir,
+u32 offset)
 {
struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
struct cdns_pcie *pcie = >pcie;
@@ -317,7 +318,8 @@ static void cdns_pcie_ep_assert_intx(struct cdns_pcie_ep 
*ep, u8 fn,
writel(0, ep->irq_cpu_addr + offset);
 }
 
-static int cdns_pcie_ep_send_legacy_irq(struct cdns_pcie_ep *ep, u8 fn, u8 
intx)
+static int cdns_pcie_ep_send_legacy_irq(struct cdns_pc

[PATCH v4 1/7] dt-bindings: PCI: pci-ep: Add binding to specify virtual function

2021-03-10 Thread Kishon Vijay Abraham I
Add binding to specify virtual function (associated with each physical
function) in endpoint mode.

Signed-off-by: Kishon Vijay Abraham I 
Reviewed-by: Rob Herring 
---
 Documentation/devicetree/bindings/pci/pci-ep.yaml | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/Documentation/devicetree/bindings/pci/pci-ep.yaml 
b/Documentation/devicetree/bindings/pci/pci-ep.yaml
index 7847bbcd4a03..ccec51ab5247 100644
--- a/Documentation/devicetree/bindings/pci/pci-ep.yaml
+++ b/Documentation/devicetree/bindings/pci/pci-ep.yaml
@@ -23,6 +23,13 @@ properties:
 default: 1
 maximum: 255
 
+  max-virtual-functions:
+description: Array representing the number of virtual functions 
corresponding to each physical
+  function
+$ref: /schemas/types.yaml#/definitions/uint8-array
+minItems: 1
+maxItems: 255
+
   max-link-speed:
 $ref: /schemas/types.yaml#/definitions/uint32
 enum: [ 1, 2, 3, 4 ]
-- 
2.17.1



[PATCH v4 2/7] PCI: endpoint: Add support to add virtual function in endpoint core

2021-03-10 Thread Kishon Vijay Abraham I
Add support to add virtual function in endpoint core. The virtual
function can only be associated with a physical function instead of a
endpoint controller. Provide APIs to associate a virtual function with
a physical function here.

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/pci/endpoint/pci-epc-core.c |  2 +-
 drivers/pci/endpoint/pci-epf-core.c | 96 -
 include/linux/pci-epf.h | 16 -
 3 files changed, 111 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/endpoint/pci-epc-core.c 
b/drivers/pci/endpoint/pci-epc-core.c
index cc8f9eb2b177..fe6d23849502 100644
--- a/drivers/pci/endpoint/pci-epc-core.c
+++ b/drivers/pci/endpoint/pci-epc-core.c
@@ -548,7 +548,7 @@ int pci_epc_add_epf(struct pci_epc *epc, struct pci_epf 
*epf,
u32 func_no;
int ret = 0;
 
-   if (IS_ERR_OR_NULL(epc))
+   if (IS_ERR_OR_NULL(epc) || epf->is_vf)
return -EINVAL;
 
if (type == PRIMARY_INTERFACE && epf->epc)
diff --git a/drivers/pci/endpoint/pci-epf-core.c 
b/drivers/pci/endpoint/pci-epf-core.c
index 7646c8660d42..3f1271a63be5 100644
--- a/drivers/pci/endpoint/pci-epf-core.c
+++ b/drivers/pci/endpoint/pci-epf-core.c
@@ -62,13 +62,20 @@ EXPORT_SYMBOL_GPL(pci_epf_type_add_cfs);
  */
 void pci_epf_unbind(struct pci_epf *epf)
 {
+   struct pci_epf *epf_vf;
+
if (!epf->driver) {
dev_WARN(>dev, "epf device not bound to driver\n");
return;
}
 
mutex_lock(>lock);
-   epf->driver->ops->unbind(epf);
+   list_for_each_entry(epf_vf, >pci_vepf, list) {
+   if (epf_vf->is_bound)
+   epf_vf->driver->ops->unbind(epf_vf);
+   }
+   if (epf->is_bound)
+   epf->driver->ops->unbind(epf);
mutex_unlock(>lock);
module_put(epf->driver->owner);
 }
@@ -83,6 +90,7 @@ EXPORT_SYMBOL_GPL(pci_epf_unbind);
  */
 int pci_epf_bind(struct pci_epf *epf)
 {
+   struct pci_epf *epf_vf;
int ret;
 
if (!epf->driver) {
@@ -94,13 +102,95 @@ int pci_epf_bind(struct pci_epf *epf)
return -EAGAIN;
 
mutex_lock(>lock);
+   list_for_each_entry(epf_vf, >pci_vepf, list) {
+   epf_vf->func_no = epf->func_no;
+   epf_vf->epc = epf->epc;
+   epf_vf->sec_epc = epf->sec_epc;
+   ret = epf_vf->driver->ops->bind(epf_vf);
+   if (ret)
+   goto ret;
+   epf_vf->is_bound = true;
+   }
+
ret = epf->driver->ops->bind(epf);
+   if (ret)
+   goto ret;
+   epf->is_bound = true;
+
+   mutex_unlock(>lock);
+   return 0;
+
+ret:
mutex_unlock(>lock);
+   pci_epf_unbind(epf);
 
return ret;
 }
 EXPORT_SYMBOL_GPL(pci_epf_bind);
 
+/**
+ * pci_epf_add_vepf() - associate virtual EP function to physical EP function
+ * @epf_pf: the physical EP function to which the virtual EP function should be
+ *   associated
+ * @epf_vf: the virtual EP function to be added
+ *
+ * A physical endpoint function can be associated with multiple virtual
+ * endpoint functions. Invoke pci_epf_add_epf() to add a virtual PCI endpoint
+ * function to a physical PCI endpoint function.
+ */
+int pci_epf_add_vepf(struct pci_epf *epf_pf, struct pci_epf *epf_vf)
+{
+   u32 vfunc_no;
+
+   if (IS_ERR_OR_NULL(epf_pf) || IS_ERR_OR_NULL(epf_vf))
+   return -EINVAL;
+
+   if (epf_pf->epc || epf_vf->epc || epf_vf->epf_pf)
+   return -EBUSY;
+
+   if (epf_pf->sec_epc || epf_vf->sec_epc)
+   return -EBUSY;
+
+   mutex_lock(_pf->lock);
+   vfunc_no = find_first_zero_bit(_pf->vfunction_num_map,
+  BITS_PER_LONG);
+   if (vfunc_no >= BITS_PER_LONG)
+   return -EINVAL;
+
+   set_bit(vfunc_no, _pf->vfunction_num_map);
+   epf_vf->vfunc_no = vfunc_no;
+
+   epf_vf->epf_pf = epf_pf;
+   epf_vf->is_vf = true;
+
+   list_add_tail(_vf->list, _pf->pci_vepf);
+   mutex_unlock(_pf->lock);
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(pci_epf_add_vepf);
+
+/**
+ * pci_epf_remove_vepf() - remove virtual EP function from physical EP function
+ * @epf_pf: the physical EP function from which the virtual EP function should
+ *   be removed
+ * @epf_vf: the virtual EP function to be removed
+ *
+ * Invoke to remove a virtual endpoint function from the physcial endpoint
+ * function.
+ */
+void pci_epf_remove_vepf(struct pci_epf *epf_pf, struct pci_epf *epf_vf)
+{
+   if (IS_ERR_OR_NULL(epf_pf) || IS_ERR_OR_NULL(epf_vf))
+   return;
+
+   mutex_lock(_pf->lock);
+   clear_bit(epf_vf->vfunc_no, _pf->vfunction_num_map);
+   list_del(_vf->list);
+   mutex_unlock(_pf->lock);
+}
+EX

[PATCH v4 0/7] Add SR-IOV support in PCIe Endpoint Core

2021-03-10 Thread Kishon Vijay Abraham I
Patch series
*) Adds support to add virtual functions to enable endpoint controller
   which supports SR-IOV capability
*) Add support in Cadence endpoint driver to configure virtual functions
*) Enable pci_endpoint_test driver to create pci_device for virtual
   functions

v1 of the patch series can be found at [1]
v2 of the patch series can be found at [2]
v3 of the patch series can be found at [3]

Here both physical functions and virtual functions use the same
pci_endpoint_test driver and existing pcitest utility can be used
to test virtual functions as well.

Changes from v3:
*) Fixed Rob's comment and added his Reviewed-by as suggested by him.

Changes from v2:
*) Fixed DT binding documentation comment by Rob
*) Fixed the error check in pci-epc-core.c

Changes from v1:
*) Re-based and Re-worked to latest kernel 5.10.0-rc2+ (now has generic
   binding for EP)

[1] -> http://lore.kernel.org/r/20191231113534.30405-1-kis...@ti.com
[2] -> http://lore.kernel.org/r/20201112175358.2653-1-kis...@ti.com
[3] -> https://lore.kernel.org/r/20210305050410.9201-1-kis...@ti.com

Kishon Vijay Abraham I (7):
  dt-bindings: PCI: pci-ep: Add binding to specify virtual function
  PCI: endpoint: Add support to add virtual function in endpoint core
  PCI: endpoint: Add support to link a physical function to a virtual
function
  PCI: endpoint: Add virtual function number in pci_epc ops
  PCI: cadence: Add support to configure virtual functions
  misc: pci_endpoint_test: Populate sriov_configure ops to configure
SR-IOV device
  Documentation: PCI: endpoint/pci-endpoint-cfs: Guide to use SR-IOV

 .../PCI/endpoint/pci-endpoint-cfs.rst |  12 +-
 .../devicetree/bindings/pci/pci-ep.yaml   |   7 +
 drivers/misc/pci_endpoint_test.c  |   1 +
 .../pci/controller/cadence/pcie-cadence-ep.c  | 251 +++---
 drivers/pci/controller/cadence/pcie-cadence.h |   7 +
 .../pci/controller/dwc/pcie-designware-ep.c   |  36 +--
 drivers/pci/controller/pcie-rcar-ep.c |  19 +-
 drivers/pci/controller/pcie-rockchip-ep.c |  18 +-
 drivers/pci/endpoint/functions/pci-epf-ntb.c  |  79 +++---
 drivers/pci/endpoint/functions/pci-epf-test.c |  66 +++--
 drivers/pci/endpoint/pci-ep-cfs.c |  24 ++
 drivers/pci/endpoint/pci-epc-core.c   | 130 ++---
 drivers/pci/endpoint/pci-epf-core.c   | 144 +-
 include/linux/pci-epc.h   |  57 ++--
 include/linux/pci-epf.h   |  16 +-
 15 files changed, 664 insertions(+), 203 deletions(-)

-- 
2.17.1



[PATCH 3/4] phy: cadence-torrent: Do not configure SERDES if it's already configured

2021-03-10 Thread Kishon Vijay Abraham I
Do not configure torrent SERDES if it's already configured.

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/phy/cadence/phy-cadence-torrent.c | 32 ---
 1 file changed, 22 insertions(+), 10 deletions(-)

diff --git a/drivers/phy/cadence/phy-cadence-torrent.c 
b/drivers/phy/cadence/phy-cadence-torrent.c
index ab51c4bf7b30..5ee1657f5a1c 100644
--- a/drivers/phy/cadence/phy-cadence-torrent.c
+++ b/drivers/phy/cadence/phy-cadence-torrent.c
@@ -371,6 +371,10 @@ static const struct phy_ops cdns_torrent_phy_ops = {
.owner  = THIS_MODULE,
 };
 
+static const struct phy_ops noop_ops = {
+   .owner  = THIS_MODULE,
+};
+
 struct cdns_reg_pairs {
u32 val;
u32 off;
@@ -2306,6 +2310,7 @@ static int cdns_torrent_phy_probe(struct platform_device 
*pdev)
struct device_node *child;
int ret, subnodes, node = 0, i;
u32 total_num_lanes = 0;
+   int already_configured;
u8 init_dp_regmap = 0;
u32 phy_type;
 
@@ -2344,16 +2349,20 @@ static int cdns_torrent_phy_probe(struct 
platform_device *pdev)
if (ret)
return ret;
 
-   ret = cdns_torrent_reset(cdns_phy);
-   if (ret)
-   goto clk_cleanup;
+   regmap_field_read(cdns_phy->phy_pma_cmn_ctrl_1, _configured);
 
-   ret = cdns_torrent_clk(cdns_phy);
-   if (ret)
-   goto clk_cleanup;
+   if (!already_configured) {
+   ret = cdns_torrent_reset(cdns_phy);
+   if (ret)
+   goto clk_cleanup;
+
+   ret = cdns_torrent_clk(cdns_phy);
+   if (ret)
+   goto clk_cleanup;
 
-   /* Enable APB */
-   reset_control_deassert(cdns_phy->apb_rst);
+   /* Enable APB */
+   reset_control_deassert(cdns_phy->apb_rst);
+   }
 
for_each_available_child_of_node(dev->of_node, child) {
struct phy *gphy;
@@ -2423,7 +2432,10 @@ static int cdns_torrent_phy_probe(struct platform_device 
*pdev)
of_property_read_u32(child, "cdns,ssc-mode",
 _phy->phys[node].ssc_mode);
 
-   gphy = devm_phy_create(dev, child, _torrent_phy_ops);
+   if (!already_configured)
+   gphy = devm_phy_create(dev, child, 
_torrent_phy_ops);
+   else
+   gphy = devm_phy_create(dev, child, _ops);
if (IS_ERR(gphy)) {
ret = PTR_ERR(gphy);
goto put_child;
@@ -2507,7 +2519,7 @@ static int cdns_torrent_phy_probe(struct platform_device 
*pdev)
goto put_lnk_rst;
}
 
-   if (cdns_phy->nsubnodes > 1) {
+   if (cdns_phy->nsubnodes > 1 && !already_configured) {
ret = cdns_torrent_phy_configure_multilink(cdns_phy);
if (ret)
goto put_lnk_rst;
-- 
2.17.1



[PATCH 2/4] phy: cadence-torrent: Group reset APIs and clock APIs

2021-03-10 Thread Kishon Vijay Abraham I
No functional change intended. Group reset APIs and clock APIs in
preparation for adding support to skip configuration if the SERDES
is already configured by bootloader.

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/phy/cadence/phy-cadence-torrent.c | 84 ++-
 1 file changed, 53 insertions(+), 31 deletions(-)

diff --git a/drivers/phy/cadence/phy-cadence-torrent.c 
b/drivers/phy/cadence/phy-cadence-torrent.c
index 3fdab0d288c4..ab51c4bf7b30 100644
--- a/drivers/phy/cadence/phy-cadence-torrent.c
+++ b/drivers/phy/cadence/phy-cadence-torrent.c
@@ -2249,6 +2249,54 @@ static int cdns_torrent_clk_register(struct 
cdns_torrent_phy *cdns_phy)
return 0;
 }
 
+static int cdns_torrent_reset(struct cdns_torrent_phy *cdns_phy)
+{
+   struct device *dev = cdns_phy->dev;
+
+   cdns_phy->phy_rst = devm_reset_control_get_exclusive_by_index(dev, 0);
+   if (IS_ERR(cdns_phy->phy_rst)) {
+   dev_err(dev, "%s: failed to get reset\n",
+   dev->of_node->full_name);
+   return PTR_ERR(cdns_phy->phy_rst);
+   }
+
+   cdns_phy->apb_rst = devm_reset_control_get_optional(dev, "torrent_apb");
+   if (IS_ERR(cdns_phy->apb_rst)) {
+   dev_err(dev, "%s: failed to get apb reset\n",
+   dev->of_node->full_name);
+   return PTR_ERR(cdns_phy->apb_rst);
+   }
+
+   return 0;
+}
+
+static int cdns_torrent_clk(struct cdns_torrent_phy *cdns_phy)
+{
+   struct device *dev = cdns_phy->dev;
+   int ret;
+
+   cdns_phy->clk = devm_clk_get(dev, "refclk");
+   if (IS_ERR(cdns_phy->clk)) {
+   dev_err(dev, "phy ref clock not found\n");
+   return PTR_ERR(cdns_phy->clk);
+   }
+
+   ret = clk_prepare_enable(cdns_phy->clk);
+   if (ret) {
+   dev_err(cdns_phy->dev, "Failed to prepare ref clock\n");
+   return ret;
+   }
+
+   cdns_phy->ref_clk_rate = clk_get_rate(cdns_phy->clk);
+   if (!(cdns_phy->ref_clk_rate)) {
+   dev_err(cdns_phy->dev, "Failed to get ref clock rate\n");
+   clk_disable_unprepare(cdns_phy->clk);
+   return -EINVAL;
+   }
+
+   return 0;
+}
+
 static int cdns_torrent_phy_probe(struct platform_device *pdev)
 {
struct cdns_torrent_phy *cdns_phy;
@@ -2274,26 +2322,6 @@ static int cdns_torrent_phy_probe(struct platform_device 
*pdev)
cdns_phy->dev = dev;
cdns_phy->init_data = data;
 
-   cdns_phy->phy_rst = devm_reset_control_get_exclusive_by_index(dev, 0);
-   if (IS_ERR(cdns_phy->phy_rst)) {
-   dev_err(dev, "%s: failed to get reset\n",
-   dev->of_node->full_name);
-   return PTR_ERR(cdns_phy->phy_rst);
-   }
-
-   cdns_phy->apb_rst = devm_reset_control_get_optional(dev, "torrent_apb");
-   if (IS_ERR(cdns_phy->apb_rst)) {
-   dev_err(dev, "%s: failed to get apb reset\n",
-   dev->of_node->full_name);
-   return PTR_ERR(cdns_phy->apb_rst);
-   }
-
-   cdns_phy->clk = devm_clk_get(dev, "refclk");
-   if (IS_ERR(cdns_phy->clk)) {
-   dev_err(dev, "phy ref clock not found\n");
-   return PTR_ERR(cdns_phy->clk);
-   }
-
cdns_phy->sd_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(cdns_phy->sd_base))
return PTR_ERR(cdns_phy->sd_base);
@@ -2316,18 +2344,13 @@ static int cdns_torrent_phy_probe(struct 
platform_device *pdev)
if (ret)
return ret;
 
-   ret = clk_prepare_enable(cdns_phy->clk);
-   if (ret) {
-   dev_err(cdns_phy->dev, "Failed to prepare ref clock\n");
+   ret = cdns_torrent_reset(cdns_phy);
+   if (ret)
goto clk_cleanup;
-   }
 
-   cdns_phy->ref_clk_rate = clk_get_rate(cdns_phy->clk);
-   if (!(cdns_phy->ref_clk_rate)) {
-   dev_err(cdns_phy->dev, "Failed to get ref clock rate\n");
-   ret = -EINVAL;
-   goto clk_disable;
-   }
+   ret = cdns_torrent_clk(cdns_phy);
+   if (ret)
+   goto clk_cleanup;
 
/* Enable APB */
reset_control_deassert(cdns_phy->apb_rst);
@@ -2505,7 +2528,6 @@ static int cdns_torrent_phy_probe(struct platform_device 
*pdev)
reset_control_put(cdns_phy->phys[i].lnk_rst);
of_node_put(child);
reset_control_assert(cdns_phy->apb_rst);
-clk_disable:
clk_disable_unprepare(cdns_phy->clk);
 clk_cleanup:
cdns_torrent_clk_cleanup(cdns_phy);
-- 
2.17.1



[PATCH 4/4] phy: cadence-torrent: Explicitly request exclusive reset control

2021-03-10 Thread Kishon Vijay Abraham I
No functional change. Since the reset controls obtained in
Torrent is exclusively used by the Torrent device, use
exclusive reset control request API calls.

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/phy/cadence/phy-cadence-torrent.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/phy/cadence/phy-cadence-torrent.c 
b/drivers/phy/cadence/phy-cadence-torrent.c
index 5ee1657f5a1c..ff8bb4b724c0 100644
--- a/drivers/phy/cadence/phy-cadence-torrent.c
+++ b/drivers/phy/cadence/phy-cadence-torrent.c
@@ -2264,7 +2264,7 @@ static int cdns_torrent_reset(struct cdns_torrent_phy 
*cdns_phy)
return PTR_ERR(cdns_phy->phy_rst);
}
 
-   cdns_phy->apb_rst = devm_reset_control_get_optional(dev, "torrent_apb");
+   cdns_phy->apb_rst = devm_reset_control_get_optional_exclusive(dev, 
"torrent_apb");
if (IS_ERR(cdns_phy->apb_rst)) {
dev_err(dev, "%s: failed to get apb reset\n",
dev->of_node->full_name);
-- 
2.17.1



[PATCH 1/4] phy: ti: j721e-wiz: Do not configure wiz if its already configured

2021-03-10 Thread Kishon Vijay Abraham I
From: Faiz Abbas 

Serdes lanes might be shared between multiple cores in some usecases
and its not possible to lock PLLs for both the lanes independently
by the two cores. This requires a bootloader to configure both the
lanes at early boot time.

To handle this case, skip all configuration if any of the lanes has
already been enabled.

Signed-off-by: Faiz Abbas 
Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/phy/ti/phy-j721e-wiz.c | 21 -
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c
index 659597645201..95905e5c4f3d 100644
--- a/drivers/phy/ti/phy-j721e-wiz.c
+++ b/drivers/phy/ti/phy-j721e-wiz.c
@@ -1132,13 +1132,14 @@ static int wiz_probe(struct platform_device *pdev)
struct device *dev = >dev;
struct device_node *node = dev->of_node;
struct platform_device *serdes_pdev;
+   bool already_configured = false;
struct device_node *child_node;
struct regmap *regmap;
struct resource res;
void __iomem *base;
struct wiz *wiz;
+   int ret, val, i;
u32 num_lanes;
-   int ret;
 
wiz = devm_kzalloc(dev, sizeof(*wiz), GFP_KERNEL);
if (!wiz)
@@ -1266,10 +1267,20 @@ static int wiz_probe(struct platform_device *pdev)
goto err_get_sync;
}
 
-   ret = wiz_init(wiz);
-   if (ret) {
-   dev_err(dev, "WIZ initialization failed\n");
-   goto err_wiz_init;
+   for (i = 0; i < wiz->num_lanes; i++) {
+   regmap_field_read(wiz->p_enable[i], );
+   if (val & (P_ENABLE | P_ENABLE_FORCE)) {
+   already_configured = true;
+   break;
+   }
+   }
+
+   if (!already_configured) {
+   ret = wiz_init(wiz);
+   if (ret) {
+   dev_err(dev, "WIZ initialization failed\n");
+   goto err_wiz_init;
+   }
}
 
serdes_pdev = of_platform_device_create(child_node, NULL, dev);
-- 
2.17.1



[PATCH 0/4] j721e-wiz/cadence-torrent: Support to skip SERDES configuration

2021-03-10 Thread Kishon Vijay Abraham I
Add support to skip SERDES configuration if it's already configured in
bootloader.

The wiz part was initially sent in [1] but that was sent more in the
context of Sierra but this is in context of Torrent. The Sierra part
would be sent later.

[1] -> http://lore.kernel.org/r/20201103035556.21260-1-kis...@ti.com

Faiz Abbas (1):
  phy: ti: j721e-wiz: Do not configure wiz if its already configured

Kishon Vijay Abraham I (3):
  phy: cadence-torrent: Group reset APIs and clock APIs
  phy: cadence-torrent: Do not configure SERDES if it's already
configured
  phy: cadence-torrent: Explicitly request exclusive reset control

 drivers/phy/cadence/phy-cadence-torrent.c | 106 ++
 drivers/phy/ti/phy-j721e-wiz.c|  21 -
 2 files changed, 86 insertions(+), 41 deletions(-)

-- 
2.17.1



[PATCH v6 11/13] dt-bindings: phy: phy-cadence-sierra: Add binding to model Sierra as clock provider

2021-03-10 Thread Kishon Vijay Abraham I
Add #clock-cells binding to model Sierra as clock provider and include
clock IDs for PLL_CMNLC and PLL_CMNLC1.

Signed-off-by: Kishon Vijay Abraham I 
Reviewed-by: Rob Herring 
---
 .../bindings/phy/phy-cadence-sierra.yaml| 17 -
 include/dt-bindings/phy/phy-cadence.h   |  4 
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/phy/phy-cadence-sierra.yaml 
b/Documentation/devicetree/bindings/phy/phy-cadence-sierra.yaml
index d210843863df..84383e2e0b34 100644
--- a/Documentation/devicetree/bindings/phy/phy-cadence-sierra.yaml
+++ b/Documentation/devicetree/bindings/phy/phy-cadence-sierra.yaml
@@ -26,6 +26,9 @@ properties:
   '#size-cells':
 const: 0
 
+  '#clock-cells':
+const: 1
+
   resets:
 minItems: 1
 maxItems: 2
@@ -49,12 +52,24 @@ properties:
 const: serdes
 
   clocks:
-maxItems: 2
+minItems: 2
+maxItems: 4
 
   clock-names:
+minItems: 2
 items:
   - const: cmn_refclk_dig_div
   - const: cmn_refclk1_dig_div
+  - const: pll0_refclk
+  - const: pll1_refclk
+
+  assigned-clocks:
+minItems: 1
+maxItems: 2
+
+  assigned-clock-parents:
+minItems: 1
+maxItems: 2
 
   cdns,autoconf:
 type: boolean
diff --git a/include/dt-bindings/phy/phy-cadence.h 
b/include/dt-bindings/phy/phy-cadence.h
index 4a5ea52a856f..4652bcb86265 100644
--- a/include/dt-bindings/phy/phy-cadence.h
+++ b/include/dt-bindings/phy/phy-cadence.h
@@ -13,4 +13,8 @@
 
 #define CDNS_TORRENT_REFCLK_DRIVER  0
 
+/* Sierra */
+#define CDNS_SIERRA_PLL_CMNLC  0
+#define CDNS_SIERRA_PLL_CMNLC1 1
+
 #endif /* _DT_BINDINGS_CADENCE_SERDES_H */
-- 
2.17.1



[PATCH v6 12/13] phy: cadence: phy-cadence-sierra: Model PLL_CMNLC and PLL_CMNLC1 as clocks (mux clocks)

2021-03-10 Thread Kishon Vijay Abraham I
Sierra has two PLLs, PLL_CMNLC and PLL_CMNLC1 and each of these PLLs has
two inputs, plllc_refclk (input from pll0_refclk) and refrcv (input from
pll1_refclk). Model PLL_CMNLC and PLL_CMNLC1 as clocks so that it's
possible to select one of these two inputs from device tree.

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/phy/cadence/Kconfig  |   1 +
 drivers/phy/cadence/phy-cadence-sierra.c | 267 ++-
 2 files changed, 265 insertions(+), 3 deletions(-)

diff --git a/drivers/phy/cadence/Kconfig b/drivers/phy/cadence/Kconfig
index 27e9d6c377e5..a62910ff5591 100644
--- a/drivers/phy/cadence/Kconfig
+++ b/drivers/phy/cadence/Kconfig
@@ -25,6 +25,7 @@ config PHY_CADENCE_DPHY
 config PHY_CADENCE_SIERRA
tristate "Cadence Sierra PHY Driver"
depends on OF && HAS_IOMEM && RESET_CONTROLLER
+   depends on COMMON_CLK
select GENERIC_PHY
help
  Enable this to support the Cadence Sierra PHY driver
diff --git a/drivers/phy/cadence/phy-cadence-sierra.c 
b/drivers/phy/cadence/phy-cadence-sierra.c
index ac32b7b0289f..039ca10db59d 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -7,6 +7,7 @@
  *
  */
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -20,10 +21,12 @@
 #include 
 #include 
 #include 
+#include 
 
 /* PHY register offsets */
 #define SIERRA_COMMON_CDB_OFFSET   0x0
 #define SIERRA_MACRO_ID_REG0x0
+#define SIERRA_CMN_PLLLC_GEN_PREG  0x42
 #define SIERRA_CMN_PLLLC_MODE_PREG 0x48
 #define SIERRA_CMN_PLLLC_LF_COEFF_MODE1_PREG   0x49
 #define SIERRA_CMN_PLLLC_LF_COEFF_MODE0_PREG   0x4A
@@ -31,6 +34,9 @@
 #define SIERRA_CMN_PLLLC_BWCAL_MODE1_PREG  0x4F
 #define SIERRA_CMN_PLLLC_BWCAL_MODE0_PREG  0x50
 #define SIERRA_CMN_PLLLC_SS_TIME_STEPSIZE_MODE_PREG0x62
+#define SIERRA_CMN_REFRCV_PREG 0x98
+#define SIERRA_CMN_REFRCV1_PREG0xB8
+#define SIERRA_CMN_PLLLC1_GEN_PREG 0xC2
 
 #define SIERRA_LANE_CDB_OFFSET(ln, block_offset, reg_offset)   \
((0x4000 << (block_offset)) + \
@@ -144,13 +150,19 @@
 #define SIERRA_MAX_LANES   16
 #define PLL_LOCK_TIME  10
 
-#define CDNS_SIERRA_INPUT_CLOCKS   3
+#define CDNS_SIERRA_OUTPUT_CLOCKS  2
+#define CDNS_SIERRA_INPUT_CLOCKS   5
 enum cdns_sierra_clock_input {
PHY_CLK,
CMN_REFCLK_DIG_DIV,
CMN_REFCLK1_DIG_DIV,
+   PLL0_REFCLK,
+   PLL1_REFCLK,
 };
 
+#define SIERRA_NUM_CMN_PLLC2
+#define SIERRA_NUM_CMN_PLLC_PARENTS2
+
 static const struct reg_field macro_id_type =
REG_FIELD(SIERRA_MACRO_ID_REG, 0, 15);
 static const struct reg_field phy_pll_cfg_1 =
@@ -158,6 +170,53 @@ static const struct reg_field phy_pll_cfg_1 =
 static const struct reg_field pllctrl_lock =
REG_FIELD(SIERRA_PLLCTRL_STATUS_PREG, 0, 0);
 
+static const char * const clk_names[] = {
+   [CDNS_SIERRA_PLL_CMNLC] = "pll_cmnlc",
+   [CDNS_SIERRA_PLL_CMNLC1] = "pll_cmnlc1",
+};
+
+enum cdns_sierra_cmn_plllc {
+   CMN_PLLLC,
+   CMN_PLLLC1,
+};
+
+struct cdns_sierra_pll_mux_reg_fields {
+   struct reg_fieldpfdclk_sel_preg;
+   struct reg_fieldplllc1en_field;
+   struct reg_fieldtermen_field;
+};
+
+static const struct cdns_sierra_pll_mux_reg_fields 
cmn_plllc_pfdclk1_sel_preg[] = {
+   [CMN_PLLLC] = {
+   .pfdclk_sel_preg = REG_FIELD(SIERRA_CMN_PLLLC_GEN_PREG, 1, 1),
+   .plllc1en_field = REG_FIELD(SIERRA_CMN_REFRCV1_PREG, 8, 8),
+   .termen_field = REG_FIELD(SIERRA_CMN_REFRCV1_PREG, 0, 0),
+   },
+   [CMN_PLLLC1] = {
+   .pfdclk_sel_preg = REG_FIELD(SIERRA_CMN_PLLLC1_GEN_PREG, 1, 1),
+   .plllc1en_field = REG_FIELD(SIERRA_CMN_REFRCV_PREG, 8, 8),
+   .termen_field = REG_FIELD(SIERRA_CMN_REFRCV_PREG, 0, 0),
+   },
+};
+
+struct cdns_sierra_pll_mux {
+   struct clk_hw   hw;
+   struct regmap_field *pfdclk_sel_preg;
+   struct regmap_field *plllc1en_field;
+   struct regmap_field *termen_field;
+   struct clk_init_dataclk_data;
+};
+
+#define to_cdns_sierra_pll_mux(_hw)\
+   container_of(_hw, struct cdns_sierra_pll_mux, hw)
+
+static const int pll_mux_parent_index[][SIERRA_NUM_CMN_PLLC_PARENTS] = {
+   [CMN_PLLLC] = { PLL0_REFCLK, PLL1_REFCLK },
+   [CMN_PLLLC1] = { PLL1_REFCLK, PLL0_REFCLK },
+};
+
+static u32 cdns_sierra_pll_mux_table[] = { 0, 1 };
+
 struct cdns_sierra_inst {
struct phy *phy;
u32 ph

[PATCH v6 13/13] phy: cadence: sierra: Enable pll_cmnlc and pll_cmnlc1 clocks

2021-03-10 Thread Kishon Vijay Abraham I
Get pll_cmnlc and pll_cmnlc1 optional clocks and enable them.
This will enable REFRCV/1 in case the pll_cmnlc/1 takes input
from REFRCV/1 respectively.

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/phy/cadence/phy-cadence-sierra.c | 40 ++--
 1 file changed, 37 insertions(+), 3 deletions(-)

diff --git a/drivers/phy/cadence/phy-cadence-sierra.c 
b/drivers/phy/cadence/phy-cadence-sierra.c
index 039ca10db59d..5c68e31c5939 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -768,6 +768,40 @@ static int cdns_sierra_phy_get_clocks(struct 
cdns_sierra_phy *sp,
return 0;
 }
 
+static int cdns_sierra_phy_enable_clocks(struct cdns_sierra_phy *sp)
+{
+   int ret;
+
+   ret = clk_prepare_enable(sp->input_clks[PHY_CLK]);
+   if (ret)
+   return ret;
+
+   ret = clk_prepare_enable(sp->output_clks[CDNS_SIERRA_PLL_CMNLC]);
+   if (ret)
+   goto err_pll_cmnlc;
+
+   ret = clk_prepare_enable(sp->output_clks[CDNS_SIERRA_PLL_CMNLC1]);
+   if (ret)
+   goto err_pll_cmnlc1;
+
+   return 0;
+
+err_pll_cmnlc1:
+   clk_disable_unprepare(sp->output_clks[CDNS_SIERRA_PLL_CMNLC]);
+
+err_pll_cmnlc:
+   clk_disable_unprepare(sp->input_clks[PHY_CLK]);
+
+   return ret;
+}
+
+static void cdns_sierra_phy_disable_clocks(struct cdns_sierra_phy *sp)
+{
+   clk_disable_unprepare(sp->output_clks[CDNS_SIERRA_PLL_CMNLC1]);
+   clk_disable_unprepare(sp->output_clks[CDNS_SIERRA_PLL_CMNLC]);
+   clk_disable_unprepare(sp->input_clks[PHY_CLK]);
+}
+
 static int cdns_sierra_phy_get_resets(struct cdns_sierra_phy *sp,
  struct device *dev)
 {
@@ -848,7 +882,7 @@ static int cdns_sierra_phy_probe(struct platform_device 
*pdev)
if (ret)
goto unregister_clk;
 
-   ret = clk_prepare_enable(sp->input_clks[PHY_CLK]);
+   ret = cdns_sierra_phy_enable_clocks(sp);
if (ret)
goto unregister_clk;
 
@@ -925,7 +959,7 @@ static int cdns_sierra_phy_probe(struct platform_device 
*pdev)
reset_control_put(sp->phys[i].lnk_rst);
of_node_put(child);
 clk_disable:
-   clk_disable_unprepare(sp->input_clks[PHY_CLK]);
+   cdns_sierra_phy_disable_clocks(sp);
reset_control_assert(sp->apb_rst);
 unregister_clk:
cdns_sierra_clk_unregister(sp);
@@ -941,6 +975,7 @@ static int cdns_sierra_phy_remove(struct platform_device 
*pdev)
reset_control_assert(phy->apb_rst);
pm_runtime_disable(>dev);
 
+   cdns_sierra_phy_disable_clocks(phy);
/*
 * The device level resets will be put automatically.
 * Need to put the subnode resets here though.
@@ -950,7 +985,6 @@ static int cdns_sierra_phy_remove(struct platform_device 
*pdev)
reset_control_put(phy->phys[i].lnk_rst);
}
 
-   clk_disable_unprepare(phy->input_clks[PHY_CLK]);
cdns_sierra_clk_unregister(phy);
 
return 0;
-- 
2.17.1



[PATCH v6 08/13] phy: cadence-torrent: Use a common header file for Cadence SERDES

2021-03-10 Thread Kishon Vijay Abraham I
No functional change. In order to have a single header file for all
Cadence SERDES move phy-cadence-torrent.h to phy-cadence.h. This is
in preparation for adding Cadence Sierra SERDES specific macros.

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/phy/cadence/phy-cadence-torrent.c| 2 +-
 .../phy/{phy-cadence-torrent.h => phy-cadence.h} | 9 +
 2 files changed, 6 insertions(+), 5 deletions(-)
 rename include/dt-bindings/phy/{phy-cadence-torrent.h => phy-cadence.h} (51%)

diff --git a/drivers/phy/cadence/phy-cadence-torrent.c 
b/drivers/phy/cadence/phy-cadence-torrent.c
index 95160da3e667..3fdab0d288c4 100644
--- a/drivers/phy/cadence/phy-cadence-torrent.c
+++ b/drivers/phy/cadence/phy-cadence-torrent.c
@@ -7,7 +7,7 @@
  */
 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
diff --git a/include/dt-bindings/phy/phy-cadence-torrent.h 
b/include/dt-bindings/phy/phy-cadence.h
similarity index 51%
rename from include/dt-bindings/phy/phy-cadence-torrent.h
rename to include/dt-bindings/phy/phy-cadence.h
index 3c92c6192493..4a5ea52a856f 100644
--- a/include/dt-bindings/phy/phy-cadence-torrent.h
+++ b/include/dt-bindings/phy/phy-cadence.h
@@ -1,15 +1,16 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
- * This header provides constants for Cadence Torrent SERDES.
+ * This header provides constants for Cadence SERDES.
  */
 
-#ifndef _DT_BINDINGS_TORRENT_SERDES_H
-#define _DT_BINDINGS_TORRENT_SERDES_H
+#ifndef _DT_BINDINGS_CADENCE_SERDES_H
+#define _DT_BINDINGS_CADENCE_SERDES_H
 
+/* Torrent */
 #define TORRENT_SERDES_NO_SSC  0
 #define TORRENT_SERDES_EXTERNAL_SSC1
 #define TORRENT_SERDES_INTERNAL_SSC2
 
 #define CDNS_TORRENT_REFCLK_DRIVER  0
 
-#endif /* _DT_BINDINGS_TORRENT_SERDES_H */
+#endif /* _DT_BINDINGS_CADENCE_SERDES_H */
-- 
2.17.1



[PATCH v6 09/13] phy: cadence: cadence-sierra: Add array of input clocks in "struct cdns_sierra_phy"

2021-03-10 Thread Kishon Vijay Abraham I
Instead of having separate structure members for each input clock, add
an array for the input clocks within "struct cdns_sierra_phy". This is
in preparation for adding more input clocks required for supporting
additional clock combination.

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/phy/cadence/phy-cadence-sierra.c | 25 ++--
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/drivers/phy/cadence/phy-cadence-sierra.c 
b/drivers/phy/cadence/phy-cadence-sierra.c
index 44c52a0842dc..a45278c30948 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -144,6 +144,13 @@
 #define SIERRA_MAX_LANES   16
 #define PLL_LOCK_TIME  10
 
+#define CDNS_SIERRA_INPUT_CLOCKS   3
+enum cdns_sierra_clock_input {
+   PHY_CLK,
+   CMN_REFCLK_DIG_DIV,
+   CMN_REFCLK1_DIG_DIV,
+};
+
 static const struct reg_field macro_id_type =
REG_FIELD(SIERRA_MACRO_ID_REG, 0, 15);
 static const struct reg_field phy_pll_cfg_1 =
@@ -197,9 +204,7 @@ struct cdns_sierra_phy {
struct regmap_field *macro_id_type;
struct regmap_field *phy_pll_cfg_1;
struct regmap_field *pllctrl_lock[SIERRA_MAX_LANES];
-   struct clk *clk;
-   struct clk *cmn_refclk_dig_div;
-   struct clk *cmn_refclk1_dig_div;
+   struct clk *input_clks[CDNS_SIERRA_INPUT_CLOCKS];
int nsubnodes;
u32 num_lanes;
bool autoconf;
@@ -281,8 +286,8 @@ static int cdns_sierra_phy_init(struct phy *gphy)
if (phy->autoconf)
return 0;
 
-   clk_set_rate(phy->cmn_refclk_dig_div, 2500);
-   clk_set_rate(phy->cmn_refclk1_dig_div, 2500);
+   clk_set_rate(phy->input_clks[CMN_REFCLK_DIG_DIV], 2500);
+   clk_set_rate(phy->input_clks[CMN_REFCLK1_DIG_DIV], 2500);
if (ins->phy_type == PHY_TYPE_PCIE) {
num_cmn_regs = phy->init_data->pcie_cmn_regs;
num_ln_regs = phy->init_data->pcie_ln_regs;
@@ -488,7 +493,7 @@ static int cdns_sierra_phy_get_clocks(struct 
cdns_sierra_phy *sp,
dev_err(dev, "failed to get clock phy_clk\n");
return PTR_ERR(clk);
}
-   sp->clk = clk;
+   sp->input_clks[PHY_CLK] = clk;
 
clk = devm_clk_get_optional(dev, "cmn_refclk_dig_div");
if (IS_ERR(clk)) {
@@ -496,7 +501,7 @@ static int cdns_sierra_phy_get_clocks(struct 
cdns_sierra_phy *sp,
ret = PTR_ERR(clk);
return ret;
}
-   sp->cmn_refclk_dig_div = clk;
+   sp->input_clks[CMN_REFCLK_DIG_DIV] = clk;
 
clk = devm_clk_get_optional(dev, "cmn_refclk1_dig_div");
if (IS_ERR(clk)) {
@@ -504,7 +509,7 @@ static int cdns_sierra_phy_get_clocks(struct 
cdns_sierra_phy *sp,
ret = PTR_ERR(clk);
return ret;
}
-   sp->cmn_refclk1_dig_div = clk;
+   sp->input_clks[CMN_REFCLK1_DIG_DIV] = clk;
 
return 0;
 }
@@ -585,7 +590,7 @@ static int cdns_sierra_phy_probe(struct platform_device 
*pdev)
if (ret)
return ret;
 
-   ret = clk_prepare_enable(sp->clk);
+   ret = clk_prepare_enable(sp->input_clks[PHY_CLK]);
if (ret)
return ret;
 
@@ -662,7 +667,7 @@ static int cdns_sierra_phy_probe(struct platform_device 
*pdev)
reset_control_put(sp->phys[i].lnk_rst);
of_node_put(child);
 clk_disable:
-   clk_disable_unprepare(sp->clk);
+   clk_disable_unprepare(sp->input_clks[PHY_CLK]);
reset_control_assert(sp->apb_rst);
return ret;
 }
-- 
2.17.1



[PATCH v6 10/13] phy: cadence: cadence-sierra: Add missing clk_disable_unprepare() in .remove callback

2021-03-10 Thread Kishon Vijay Abraham I
commit 44d30d622821 ("phy: cadence: Add driver for Sierra PHY") enabled
the clock in probe and failed to disable in remove callback. Add missing
clk_disable_unprepare() in cdns_sierra_phy_remove().

Fixes: 44d30d622821 ("phy: cadence: Add driver for Sierra PHY")
Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/phy/cadence/phy-cadence-sierra.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/phy/cadence/phy-cadence-sierra.c 
b/drivers/phy/cadence/phy-cadence-sierra.c
index a45278c30948..ac32b7b0289f 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -689,6 +689,9 @@ static int cdns_sierra_phy_remove(struct platform_device 
*pdev)
reset_control_assert(phy->phys[i].lnk_rst);
reset_control_put(phy->phys[i].lnk_rst);
}
+
+   clk_disable_unprepare(phy->input_clks[PHY_CLK]);
+
return 0;
 }
 
-- 
2.17.1



[PATCH v6 07/13] phy: cadence: cadence-sierra: Explicitly request exclusive reset control

2021-03-10 Thread Kishon Vijay Abraham I
No functional change. Since the reset controls obtained in
Sierra is exclusively used by the Sierra device, use
exclusive reset control request API calls.

Signed-off-by: Kishon Vijay Abraham I 
Reviewed-by: Philipp Zabel 
---
 drivers/phy/cadence/phy-cadence-sierra.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/phy/cadence/phy-cadence-sierra.c 
b/drivers/phy/cadence/phy-cadence-sierra.c
index 935f165404e4..44c52a0842dc 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -514,14 +514,14 @@ static int cdns_sierra_phy_get_resets(struct 
cdns_sierra_phy *sp,
 {
struct reset_control *rst;
 
-   rst = devm_reset_control_get(dev, "sierra_reset");
+   rst = devm_reset_control_get_exclusive(dev, "sierra_reset");
if (IS_ERR(rst)) {
dev_err(dev, "failed to get reset\n");
return PTR_ERR(rst);
}
sp->phy_rst = rst;
 
-   rst = devm_reset_control_get_optional(dev, "sierra_apb");
+   rst = devm_reset_control_get_optional_exclusive(dev, "sierra_apb");
if (IS_ERR(rst)) {
dev_err(dev, "failed to get apb reset\n");
return PTR_ERR(rst);
-- 
2.17.1



[PATCH v6 05/13] phy: cadence: cadence-sierra: Move all clk_get_*() to a separate function

2021-03-10 Thread Kishon Vijay Abraham I
No functional change. Group all devm_clk_get_optional() to a
separate function.

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/phy/cadence/phy-cadence-sierra.c | 57 +++-
 1 file changed, 35 insertions(+), 22 deletions(-)

diff --git a/drivers/phy/cadence/phy-cadence-sierra.c 
b/drivers/phy/cadence/phy-cadence-sierra.c
index f7ba0ed416bc..7bf1b4c7774a 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -477,6 +477,38 @@ static int cdns_regmap_init_blocks(struct cdns_sierra_phy 
*sp,
return 0;
 }
 
+static int cdns_sierra_phy_get_clocks(struct cdns_sierra_phy *sp,
+ struct device *dev)
+{
+   struct clk *clk;
+   int ret;
+
+   clk = devm_clk_get_optional(dev, "phy_clk");
+   if (IS_ERR(clk)) {
+   dev_err(dev, "failed to get clock phy_clk\n");
+   return PTR_ERR(clk);
+   }
+   sp->clk = clk;
+
+   clk = devm_clk_get_optional(dev, "cmn_refclk_dig_div");
+   if (IS_ERR(clk)) {
+   dev_err(dev, "cmn_refclk_dig_div clock not found\n");
+   ret = PTR_ERR(clk);
+   return ret;
+   }
+   sp->cmn_refclk_dig_div = clk;
+
+   clk = devm_clk_get_optional(dev, "cmn_refclk1_dig_div");
+   if (IS_ERR(clk)) {
+   dev_err(dev, "cmn_refclk1_dig_div clock not found\n");
+   ret = PTR_ERR(clk);
+   return ret;
+   }
+   sp->cmn_refclk1_dig_div = clk;
+
+   return 0;
+}
+
 static int cdns_sierra_phy_probe(struct platform_device *pdev)
 {
struct cdns_sierra_phy *sp;
@@ -487,7 +519,6 @@ static int cdns_sierra_phy_probe(struct platform_device 
*pdev)
unsigned int id_value;
int i, ret, node = 0;
void __iomem *base;
-   struct clk *clk;
struct device_node *dn = dev->of_node, *child;
 
if (of_get_child_count(dn) == 0)
@@ -524,11 +555,9 @@ static int cdns_sierra_phy_probe(struct platform_device 
*pdev)
 
platform_set_drvdata(pdev, sp);
 
-   sp->clk = devm_clk_get_optional(dev, "phy_clk");
-   if (IS_ERR(sp->clk)) {
-   dev_err(dev, "failed to get clock phy_clk\n");
-   return PTR_ERR(sp->clk);
-   }
+   ret = cdns_sierra_phy_get_clocks(sp, dev);
+   if (ret)
+   return ret;
 
sp->phy_rst = devm_reset_control_get(dev, "sierra_reset");
if (IS_ERR(sp->phy_rst)) {
@@ -542,22 +571,6 @@ static int cdns_sierra_phy_probe(struct platform_device 
*pdev)
return PTR_ERR(sp->apb_rst);
}
 
-   clk = devm_clk_get_optional(dev, "cmn_refclk_dig_div");
-   if (IS_ERR(clk)) {
-   dev_err(dev, "cmn_refclk_dig_div clock not found\n");
-   ret = PTR_ERR(clk);
-   return ret;
-   }
-   sp->cmn_refclk_dig_div = clk;
-
-   clk = devm_clk_get_optional(dev, "cmn_refclk1_dig_div");
-   if (IS_ERR(clk)) {
-   dev_err(dev, "cmn_refclk1_dig_div clock not found\n");
-   ret = PTR_ERR(clk);
-   return ret;
-   }
-   sp->cmn_refclk1_dig_div = clk;
-
ret = clk_prepare_enable(sp->clk);
if (ret)
return ret;
-- 
2.17.1



[PATCH v6 06/13] phy: cadence: cadence-sierra: Move all reset_control_get*() to a separate function

2021-03-10 Thread Kishon Vijay Abraham I
No functional change. Group devm_reset_control_get() and
devm_reset_control_get_optional() to a separate function.

Signed-off-by: Kishon Vijay Abraham I 
Reviewed-by: Philipp Zabel 
---
 drivers/phy/cadence/phy-cadence-sierra.c | 36 
 1 file changed, 25 insertions(+), 11 deletions(-)

diff --git a/drivers/phy/cadence/phy-cadence-sierra.c 
b/drivers/phy/cadence/phy-cadence-sierra.c
index 7bf1b4c7774a..935f165404e4 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -509,6 +509,28 @@ static int cdns_sierra_phy_get_clocks(struct 
cdns_sierra_phy *sp,
return 0;
 }
 
+static int cdns_sierra_phy_get_resets(struct cdns_sierra_phy *sp,
+ struct device *dev)
+{
+   struct reset_control *rst;
+
+   rst = devm_reset_control_get(dev, "sierra_reset");
+   if (IS_ERR(rst)) {
+   dev_err(dev, "failed to get reset\n");
+   return PTR_ERR(rst);
+   }
+   sp->phy_rst = rst;
+
+   rst = devm_reset_control_get_optional(dev, "sierra_apb");
+   if (IS_ERR(rst)) {
+   dev_err(dev, "failed to get apb reset\n");
+   return PTR_ERR(rst);
+   }
+   sp->apb_rst = rst;
+
+   return 0;
+}
+
 static int cdns_sierra_phy_probe(struct platform_device *pdev)
 {
struct cdns_sierra_phy *sp;
@@ -559,17 +581,9 @@ static int cdns_sierra_phy_probe(struct platform_device 
*pdev)
if (ret)
return ret;
 
-   sp->phy_rst = devm_reset_control_get(dev, "sierra_reset");
-   if (IS_ERR(sp->phy_rst)) {
-   dev_err(dev, "failed to get reset\n");
-   return PTR_ERR(sp->phy_rst);
-   }
-
-   sp->apb_rst = devm_reset_control_get_optional(dev, "sierra_apb");
-   if (IS_ERR(sp->apb_rst)) {
-   dev_err(dev, "failed to get apb reset\n");
-   return PTR_ERR(sp->apb_rst);
-   }
+   ret = cdns_sierra_phy_get_resets(sp, dev);
+   if (ret)
+   return ret;
 
ret = clk_prepare_enable(sp->clk);
if (ret)
-- 
2.17.1



[PATCH v6 02/13] phy: ti: j721e-wiz: Invoke wiz_init() before of_platform_device_create()

2021-03-10 Thread Kishon Vijay Abraham I
Invoke wiz_init() before configuring anything else in Sierra/Torrent
(invoked as part of of_platform_device_create()). wiz_init() resets the
SERDES device and any configuration done in the probe() of
Sierra/Torrent will be lost. In order to prevent SERDES configuration
from getting reset, invoke wiz_init() immediately before invoking
of_platform_device_create().

Fixes: 091876cc355d ("phy: ti: j721e-wiz: Add support for WIZ module present in 
TI J721E SoC")
Signed-off-by: Kishon Vijay Abraham I 
Cc:  # v5.10
---
 drivers/phy/ti/phy-j721e-wiz.c | 17 +++--
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c
index 995c7dbec77b..1bb73822f44a 100644
--- a/drivers/phy/ti/phy-j721e-wiz.c
+++ b/drivers/phy/ti/phy-j721e-wiz.c
@@ -1262,27 +1262,24 @@ static int wiz_probe(struct platform_device *pdev)
goto err_get_sync;
}
 
+   ret = wiz_init(wiz);
+   if (ret) {
+   dev_err(dev, "WIZ initialization failed\n");
+   goto err_wiz_init;
+   }
+
serdes_pdev = of_platform_device_create(child_node, NULL, dev);
if (!serdes_pdev) {
dev_WARN(dev, "Unable to create SERDES platform device\n");
ret = -ENOMEM;
-   goto err_pdev_create;
-   }
-   wiz->serdes_pdev = serdes_pdev;
-
-   ret = wiz_init(wiz);
-   if (ret) {
-   dev_err(dev, "WIZ initialization failed\n");
goto err_wiz_init;
}
+   wiz->serdes_pdev = serdes_pdev;
 
of_node_put(child_node);
return 0;
 
 err_wiz_init:
-   of_platform_device_destroy(_pdev->dev, NULL);
-
-err_pdev_create:
wiz_clock_cleanup(wiz, node);
 
 err_get_sync:
-- 
2.17.1



[PATCH v6 03/13] phy: cadence: cadence-sierra: Create PHY only for "phy" or "link" sub-nodes

2021-03-10 Thread Kishon Vijay Abraham I
Cadence Sierra PHY driver registers PHY using devm_phy_create()
for all sub-nodes of Sierra device tree node. However Sierra device
tree node can have sub-nodes for the various clocks in addtion to the
PHY. Use devm_phy_create() only for nodes with name "phy" (or "link"
for old device tree) which represent the actual PHY.

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/phy/cadence/phy-cadence-sierra.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/phy/cadence/phy-cadence-sierra.c 
b/drivers/phy/cadence/phy-cadence-sierra.c
index 19f32ae877b9..f7ba0ed416bc 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -577,6 +577,10 @@ static int cdns_sierra_phy_probe(struct platform_device 
*pdev)
for_each_available_child_of_node(dn, child) {
struct phy *gphy;
 
+   if (!(of_node_name_eq(child, "phy") ||
+ of_node_name_eq(child, "link")))
+   continue;
+
sp->phys[node].lnk_rst =
of_reset_control_array_get_exclusive(child);
 
-- 
2.17.1



[PATCH v6 04/13] phy: ti: j721e-wiz: Get PHY properties only for "phy" or "link" subnode

2021-03-10 Thread Kishon Vijay Abraham I
"serdes" node (child node of WIZ) can have sub-nodes for representing links
or it can have sub-nodes for representing the various clocks within the
serdes. Instead of trying to read "reg" from every child node used for
assigning "lane_phy_type", read only if the child node's name is "phy"
or "link" subnode.
Ideally all PHY dt nodes should have node name as "phy", however
existing devicetree used "link" as subnode. So in order to maintain old
DT compatibility get PHY properties for "phy" or "link" subnode.

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/phy/ti/phy-j721e-wiz.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c
index 1bb73822f44a..659597645201 100644
--- a/drivers/phy/ti/phy-j721e-wiz.c
+++ b/drivers/phy/ti/phy-j721e-wiz.c
@@ -1102,6 +1102,10 @@ static int wiz_get_lane_phy_types(struct device *dev, 
struct wiz *wiz)
u32 reg, num_lanes = 1, phy_type = PHY_NONE;
int ret, i;
 
+   if (!(of_node_name_eq(subnode, "phy") ||
+ of_node_name_eq(subnode, "link")))
+   continue;
+
ret = of_property_read_u32(subnode, "reg", );
if (ret) {
dev_err(dev,
-- 
2.17.1



[PATCH v6 01/13] phy: cadence: Sierra: Fix PHY power_on sequence

2021-03-10 Thread Kishon Vijay Abraham I
Commit 44d30d622821d ("phy: cadence: Add driver for Sierra PHY")
de-asserts PHY_RESET even before the configurations are loaded in
phy_init(). However PHY_RESET should be de-asserted only after
all the configurations has been initialized, instead of de-asserting
in probe. Fix it here.

Fixes: 44d30d622821d ("phy: cadence: Add driver for Sierra PHY")
Signed-off-by: Kishon Vijay Abraham I 
Cc:  # v5.4+
Reviewed-by: Philipp Zabel 
---
 drivers/phy/cadence/phy-cadence-sierra.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/phy/cadence/phy-cadence-sierra.c 
b/drivers/phy/cadence/phy-cadence-sierra.c
index 26a0badabe38..19f32ae877b9 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -319,6 +319,12 @@ static int cdns_sierra_phy_on(struct phy *gphy)
u32 val;
int ret;
 
+   ret = reset_control_deassert(sp->phy_rst);
+   if (ret) {
+   dev_err(dev, "Failed to take the PHY out of reset\n");
+   return ret;
+   }
+
/* Take the PHY lane group out of reset */
ret = reset_control_deassert(ins->lnk_rst);
if (ret) {
@@ -616,7 +622,6 @@ static int cdns_sierra_phy_probe(struct platform_device 
*pdev)
 
pm_runtime_enable(dev);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-   reset_control_deassert(sp->phy_rst);
return PTR_ERR_OR_ZERO(phy_provider);
 
 put_child:
-- 
2.17.1



[PATCH v6 00/13] PHY: Add support in Sierra to use external clock

2021-03-10 Thread Kishon Vijay Abraham I
Patch series adds support in Sierra driver to use external clock.

v1 of the patch series can be found @ [1]
v2 of the patch series can be found @ [2]
v3 of the patch series can be found @ [3]
v5 of the patch series can be found @ [5]
v6 of the patch series can be found @ [6]

Changes from v5:
1) Added Rob's Reviewed-by for the DT binding
2) Fixed another error handling case pointed out by Swapnil
3) Fixed few checkpatch errors.

Changes from v4:
1) Fixed couple of error handling cases
2) Added reviewed by from Philipp Zabel
3) Fixed couple of patch commit subjects to be uniform with other
patches.

Changes from v3:
1) Instead of adding separate subnodes for each clock, just add
#clock-cells in Sierra SERDES nodes and model the clocks. This is
in alignment with Rob's comment for a different series [4]
2) Removed device tree changes from the series.

Changes from v2:
1) Add depends on COMMON_CLK in Sierra
2) Add modelling PLL_CMNLC and PLL_CMNLC1 as clocks into a separate
patch
3) Disable clocks in Sierra driver remove

Changes from v1:
1) Remove the part that prevents configuration if the SERDES is already
   configured and focus only on using external clock and the associated
   cleanups
2) Change patch ordering
3) Use exclusive reset control APIs
4) Fix error handling code
5) Include DT patches in this series (I can send this separately to DT
MAINTAINER once the driver patches are merged)

[1] -> http://lore.kernel.org/r/20201103035556.21260-1-kis...@ti.com
[2] -> http://lore.kernel.org/r/20201222070520.28132-1-kis...@ti.com
[3] -> http://lore.kernel.org/r/20201224111627.32590-1-kis...@ti.com
[4] -> http://lore.kernel.org/r/20210108025943.ga1790...@robh.at.kernel.org
[5] -> https://lore.kernel.org/r/20210304044122.15166-1-kis...@ti.com
[6] -> https://lore.kernel.org/r/20210308050732.7140-1-kis...@ti.com

Kishon Vijay Abraham I (13):
  phy: cadence: Sierra: Fix PHY power_on sequence
  phy: ti: j721e-wiz: Invoke wiz_init() before
of_platform_device_create()
  phy: cadence: cadence-sierra: Create PHY only for "phy" or "link"
sub-nodes
  phy: ti: j721e-wiz: Get PHY properties only for "phy" or "link"
subnode
  phy: cadence: cadence-sierra: Move all clk_get_*() to a separate
function
  phy: cadence: cadence-sierra: Move all reset_control_get*() to a
separate function
  phy: cadence: cadence-sierra: Explicitly request exclusive reset
control
  phy: cadence-torrent: Use a common header file for Cadence SERDES
  phy: cadence: cadence-sierra: Add array of input clocks in "struct
cdns_sierra_phy"
  phy: cadence: cadence-sierra: Add missing clk_disable_unprepare() in
.remove callback
  dt-bindings: phy: phy-cadence-sierra: Add binding to model Sierra as
clock provider
  phy: cadence: phy-cadence-sierra: Model PLL_CMNLC and PLL_CMNLC1 as
clocks (mux clocks)
  phy: cadence: sierra: Enable pll_cmnlc and pll_cmnlc1 clocks

 .../bindings/phy/phy-cadence-sierra.yaml  |  17 +-
 drivers/phy/cadence/Kconfig   |   1 +
 drivers/phy/cadence/phy-cadence-sierra.c  | 419 --
 drivers/phy/cadence/phy-cadence-torrent.c |   2 +-
 drivers/phy/ti/phy-j721e-wiz.c|  21 +-
 include/dt-bindings/phy/phy-cadence-torrent.h |  15 -
 include/dt-bindings/phy/phy-cadence.h |  20 +
 7 files changed, 428 insertions(+), 67 deletions(-)
 delete mode 100644 include/dt-bindings/phy/phy-cadence-torrent.h
 create mode 100644 include/dt-bindings/phy/phy-cadence.h

-- 
2.17.1



Re: [PATCH v3 0/6] AM64: Add SERDES driver support

2021-03-10 Thread Kishon Vijay Abraham I
Hi,

On 10/03/21 5:38 pm, Kishon Vijay Abraham I wrote:
> AM64 uses the same SERDES as in J7200, however AM642 EVM doesn't
> have a clock generator (unlike J7200 base board). Here the clock from
> the SERDES has to be routed to the PCIE connector. This series adds
> support to drive reference clock output from SERDES and also adds
> SERDES (torrent) and SERDES wrapper (WIZ) bindings.
> 
> v1 of the patch series can be found @ [1]
> v2 of the patch series can be found @ [3]

Failed to note the dependency here. This series depends on
http://lore.kernel.org/r/20210310112745.3445-1-kis...@ti.com

As mentioned in the cover letter of that patch series, that series
should be merged and an immutable tag should be provided and used both
in phy tree and DT tree maintained by Nishanth.

Thanks
Kishon

> 
> Changes from v2:
> *) Sent the DT bindings as a separate series [4]
> *) Remove enabling PHY output clock in isolation mode
> 
> Changes from v1:
> *) Model the internal clocks without device tree input (Add #clock-cells
>to SERDES DT nodes for getting a reference to the clock using index
>to phandle). This is in accordance with comment given by Rob [2].
>However the existing method to model clocks from device tree is not
>removed to support upstreamed device tree.
> *) Included a patch to fix modifying static data by instance specific
>initializations.
> *) Added a fix to delete "clk_div_sel" clk provider during cleanup
> 
> [1] -> https://lore.kernel.org/r/20201224114250.1083-1-kis...@ti.com
> [2] -> http://lore.kernel.org/r/20210108025943.ga1790...@robh.at.kernel.org
> [3] -> http://lore.kernel.org/r/20210222112314.10772-1-kis...@ti.com
> [4] -> http://lore.kernel.org/r/20210310112745.3445-1-kis...@ti.com
> 
> Kishon Vijay Abraham I (6):
>   phy: ti: j721e-wiz: Remove "regmap_field" from wiz_clk_{mux|div}_sel
>   phy: ti: j721e-wiz: Delete "clk_div_sel" clk provider during cleanup
>   phy: ti: j721e-wiz: Configure full rate divider for AM64
>   phy: ti: j721e-wiz: Model the internal clocks without device tree
> input
>   phy: ti: j721e-wiz: Enable reference clock output in cmn_refclk_
>   phy: cadence-torrent: Add support to drive refclk out
> 
>  drivers/phy/cadence/Kconfig   |   1 +
>  drivers/phy/cadence/phy-cadence-torrent.c | 188 +++-
>  drivers/phy/ti/phy-j721e-wiz.c| 349 +++---
>  3 files changed, 488 insertions(+), 50 deletions(-)
> 


[PATCH v3 6/6] phy: cadence-torrent: Add support to drive refclk out

2021-03-10 Thread Kishon Vijay Abraham I
cmn_refclk_ lines in Torrent SERDES is used for connecting external
reference clock. cmn_refclk_ can also be configured to output the
reference clock. Model this derived reference clock as a "clock" so that
platforms like AM642 EVM can enable it.

This is used by PCIe to use the same refclk both in local SERDES
and remote device. Add support here to drive refclk out.

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/phy/cadence/Kconfig   |   1 +
 drivers/phy/cadence/phy-cadence-torrent.c | 188 +-
 2 files changed, 186 insertions(+), 3 deletions(-)

diff --git a/drivers/phy/cadence/Kconfig b/drivers/phy/cadence/Kconfig
index 432832bdbd16..27e9d6c377e5 100644
--- a/drivers/phy/cadence/Kconfig
+++ b/drivers/phy/cadence/Kconfig
@@ -7,6 +7,7 @@ config PHY_CADENCE_TORRENT
tristate "Cadence Torrent PHY driver"
depends on OF
depends on HAS_IOMEM
+   depends on COMMON_CLK
select GENERIC_PHY
help
  Support for Cadence Torrent PHY.
diff --git a/drivers/phy/cadence/phy-cadence-torrent.c 
b/drivers/phy/cadence/phy-cadence-torrent.c
index 591a15834b48..c6fee7f75f57 100644
--- a/drivers/phy/cadence/phy-cadence-torrent.c
+++ b/drivers/phy/cadence/phy-cadence-torrent.c
@@ -7,7 +7,9 @@
  */
 
 #include 
+#include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -84,6 +86,8 @@
 #define CMN_PLLSM1_PLLLOCK_TMR 0x0034U
 #define CMN_CDIAG_CDB_PWRI_OVRD0x0041U
 #define CMN_CDIAG_XCVRC_PWRI_OVRD  0x0047U
+#define CMN_CDIAG_REFCLK_OVRD  0x004CU
+#define CMN_CDIAG_REFCLK_DRV0_CTRL 0x0050U
 #define CMN_BGCAL_INIT_TMR 0x0064U
 #define CMN_BGCAL_ITER_TMR 0x0065U
 #define CMN_IBCAL_INIT_TMR 0x0074U
@@ -206,6 +210,7 @@
 #define RX_DIAG_ACYA   0x01FFU
 
 /* PHY PCS common registers */
+#define PHY_PIPE_CMN_CTRL1 0xU
 #define PHY_PLL_CFG0x000EU
 #define PHY_PIPE_USB3_GEN2_PRE_CFG00x0020U
 #define PHY_PIPE_USB3_GEN2_POST_CFG0   0x0022U
@@ -216,6 +221,10 @@
 #define PHY_PMA_CMN_CTRL2  0x0001U
 #define PHY_PMA_PLL_RAW_CTRL   0x0003U
 
+static const char * const clk_names[] = {
+   [CDNS_TORRENT_REFCLK_DRIVER] = "refclk-driver",
+};
+
 static const struct reg_field phy_pll_cfg =
REG_FIELD(PHY_PLL_CFG, 0, 1);
 
@@ -231,6 +240,26 @@ static const struct reg_field phy_pma_pll_raw_ctrl =
 static const struct reg_field phy_reset_ctrl =
REG_FIELD(PHY_RESET, 8, 8);
 
+static const struct reg_field phy_pipe_cmn_ctrl1_0 = 
REG_FIELD(PHY_PIPE_CMN_CTRL1, 0, 0);
+
+#define REFCLK_OUT_NUM_CMN_CONFIG  5
+
+enum cdns_torrent_refclk_out_cmn {
+   CMN_CDIAG_REFCLK_OVRD_4,
+   CMN_CDIAG_REFCLK_DRV0_CTRL_1,
+   CMN_CDIAG_REFCLK_DRV0_CTRL_4,
+   CMN_CDIAG_REFCLK_DRV0_CTRL_5,
+   CMN_CDIAG_REFCLK_DRV0_CTRL_6,
+};
+
+static const struct reg_field refclk_out_cmn_cfg[] = {
+   [CMN_CDIAG_REFCLK_OVRD_4]   = REG_FIELD(CMN_CDIAG_REFCLK_OVRD, 4, 
4),
+   [CMN_CDIAG_REFCLK_DRV0_CTRL_1]  = REG_FIELD(CMN_CDIAG_REFCLK_DRV0_CTRL, 
1, 1),
+   [CMN_CDIAG_REFCLK_DRV0_CTRL_4]  = REG_FIELD(CMN_CDIAG_REFCLK_DRV0_CTRL, 
4, 4),
+   [CMN_CDIAG_REFCLK_DRV0_CTRL_5]  = REG_FIELD(CMN_CDIAG_REFCLK_DRV0_CTRL, 
5, 5),
+   [CMN_CDIAG_REFCLK_DRV0_CTRL_6]  = REG_FIELD(CMN_CDIAG_REFCLK_DRV0_CTRL, 
6, 6),
+};
+
 enum cdns_torrent_phy_type {
TYPE_NONE,
TYPE_DP,
@@ -279,6 +308,8 @@ struct cdns_torrent_phy {
struct regmap_field *phy_pma_cmn_ctrl_2;
struct regmap_field *phy_pma_pll_raw_ctrl;
struct regmap_field *phy_reset_ctrl;
+   struct clk *clks[CDNS_TORRENT_REFCLK_DRIVER + 1];
+   struct clk_onecell_data clk_data;
 };
 
 enum phy_powerstate {
@@ -288,6 +319,16 @@ enum phy_powerstate {
POWERSTATE_A3 = 3,
 };
 
+struct cdns_torrent_derived_refclk {
+   struct clk_hw   hw;
+   struct regmap_field *phy_pipe_cmn_ctrl1_0;
+   struct regmap_field *cmn_fields[REFCLK_OUT_NUM_CMN_CONFIG];
+   struct clk_init_dataclk_data;
+};
+
+#define to_cdns_torrent_derived_refclk(_hw)\
+   container_of(_hw, struct cdns_torrent_derived_refclk, 
hw)
+
 static int cdns_torrent_phy_init(struct phy *phy);
 static int cdns_torrent_dp_init(struct phy *phy);
 static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy,
@@ -1604,6 +1645,108 @@ static int cdns_torrent_dp_run(struct cdns_torrent_phy 
*cdns_phy, u32 num_lanes)
return ret;
 }
 
+static int cdns_torrent_derived_refclk_enable(struct clk_hw *hw)
+{
+   struct cdns_torrent_derived_refclk *derived_refclk = 
to_cdns_torrent_derived_refclk(hw);
+
+   
regmap_field_write(derived_refclk->cmn_fields[CMN_CDIAG_REFCLK_DRV0_CTRL_6], 0);
+   
regmap_field_write(derived_refclk->cmn_fields[CMN_CDIAG_REFCLK_DRV0_CTRL_4], 1);
+   
regmap_fi

[PATCH v3 5/6] phy: ti: j721e-wiz: Enable reference clock output in cmn_refclk_

2021-03-10 Thread Kishon Vijay Abraham I
cmn_refclk_ lines in Torrent SERDES is used for connecting external
reference clock. cmn_refclk_ can also be configured to output the
reference clock. In order to drive the refclk out from the SERDES
(Cadence Torrent), PHY_EN_REFCLK should be set in SERDES_RST of WIZ.
Model PHY_EN_REFCLK as a clock, so that platforms like AM642 EVM can
enable it.

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/phy/ti/phy-j721e-wiz.c | 89 ++
 1 file changed, 89 insertions(+)

diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c
index f9299dcdbdb7..03896240a5d5 100644
--- a/drivers/phy/ti/phy-j721e-wiz.c
+++ b/drivers/phy/ti/phy-j721e-wiz.c
@@ -66,6 +66,7 @@ enum wiz_clock_input {
 
 static const struct reg_field por_en = REG_FIELD(WIZ_SERDES_CTRL, 31, 31);
 static const struct reg_field phy_reset_n = REG_FIELD(WIZ_SERDES_RST, 31, 31);
+static const struct reg_field phy_en_refclk = REG_FIELD(WIZ_SERDES_RST, 30, 
30);
 static const struct reg_field pll1_refclk_mux_sel =
REG_FIELD(WIZ_SERDES_RST, 29, 29);
 static const struct reg_field pll0_refclk_mux_sel =
@@ -86,6 +87,7 @@ static const char * const output_clk_names[] = {
[TI_WIZ_PLL0_REFCLK] = "pll0-refclk",
[TI_WIZ_PLL1_REFCLK] = "pll1-refclk",
[TI_WIZ_REFCLK_DIG] = "refclk-dig",
+   [TI_WIZ_PHY_EN_REFCLK] = "phy-en-refclk",
 };
 
 static const struct reg_field p_enable[WIZ_MAX_LANES] = {
@@ -158,6 +160,14 @@ struct wiz_clk_div_sel {
const char  *node_name;
 };
 
+struct wiz_phy_en_refclk {
+   struct clk_hw   hw;
+   struct regmap_field *phy_en_refclk;
+   struct clk_init_dataclk_data;
+};
+
+#define to_wiz_phy_en_refclk(_hw) container_of(_hw, struct wiz_phy_en_refclk, 
hw)
+
 static const struct wiz_clk_mux_sel clk_mux_sel_16g[] = {
{
/*
@@ -237,6 +247,7 @@ struct wiz {
unsigned intclk_div_sel_num;
struct regmap_field *por_en;
struct regmap_field *phy_reset_n;
+   struct regmap_field *phy_en_refclk;
struct regmap_field *p_enable[WIZ_MAX_LANES];
struct regmap_field *p_align[WIZ_MAX_LANES];
struct regmap_field *p_raw_auto_start[WIZ_MAX_LANES];
@@ -469,6 +480,76 @@ static int wiz_regfield_init(struct wiz *wiz)
return PTR_ERR(wiz->typec_ln10_swap);
}
 
+   wiz->phy_en_refclk = devm_regmap_field_alloc(dev, regmap, 
phy_en_refclk);
+   if (IS_ERR(wiz->phy_en_refclk)) {
+   dev_err(dev, "PHY_EN_REFCLK reg field init failed\n");
+   return PTR_ERR(wiz->phy_en_refclk);
+   }
+
+   return 0;
+}
+
+static int wiz_phy_en_refclk_enable(struct clk_hw *hw)
+{
+   struct wiz_phy_en_refclk *wiz_phy_en_refclk = to_wiz_phy_en_refclk(hw);
+   struct regmap_field *phy_en_refclk = wiz_phy_en_refclk->phy_en_refclk;
+
+   regmap_field_write(phy_en_refclk, 1);
+
+   return 0;
+}
+
+static void wiz_phy_en_refclk_disable(struct clk_hw *hw)
+{
+   struct wiz_phy_en_refclk *wiz_phy_en_refclk = to_wiz_phy_en_refclk(hw);
+   struct regmap_field *phy_en_refclk = wiz_phy_en_refclk->phy_en_refclk;
+
+   regmap_field_write(phy_en_refclk, 0);
+}
+
+static int wiz_phy_en_refclk_is_enabled(struct clk_hw *hw)
+{
+   struct wiz_phy_en_refclk *wiz_phy_en_refclk = to_wiz_phy_en_refclk(hw);
+   struct regmap_field *phy_en_refclk = wiz_phy_en_refclk->phy_en_refclk;
+   int val;
+
+   regmap_field_read(phy_en_refclk, );
+
+   return !!val;
+}
+
+static const struct clk_ops wiz_phy_en_refclk_ops = {
+   .enable = wiz_phy_en_refclk_enable,
+   .disable = wiz_phy_en_refclk_disable,
+   .is_enabled = wiz_phy_en_refclk_is_enabled,
+};
+
+static int wiz_phy_en_refclk_register(struct wiz *wiz)
+{
+   struct wiz_phy_en_refclk *wiz_phy_en_refclk;
+   struct device *dev = wiz->dev;
+   struct clk_init_data *init;
+   struct clk *clk;
+
+   wiz_phy_en_refclk = devm_kzalloc(dev, sizeof(*wiz_phy_en_refclk), 
GFP_KERNEL);
+   if (!wiz_phy_en_refclk)
+   return -ENOMEM;
+
+   init = _phy_en_refclk->clk_data;
+
+   init->ops = _phy_en_refclk_ops;
+   init->flags = 0;
+   init->name = output_clk_names[TI_WIZ_PHY_EN_REFCLK];
+
+   wiz_phy_en_refclk->phy_en_refclk = wiz->phy_en_refclk;
+   wiz_phy_en_refclk->hw.init = init;
+
+   clk = devm_clk_register(dev, _phy_en_refclk->hw);
+   if (IS_ERR(clk))
+   return PTR_ERR(clk);
+
+   wiz->output_clks[TI_WIZ_PHY_EN_REFCLK] = clk;
+
return 0;
 }
 
@@ -724,6 +805,8 @@ static void wiz_clock_cleanup(struct wiz *wiz, struct 
device_node *node)
of_clk_del_provider(clk_node);
of_node_put(clk_node);
}
+
+   of_clk_del_provider(wiz->dev->of_node);
 }

[PATCH v3 4/6] phy: ti: j721e-wiz: Model the internal clocks without device tree input

2021-03-10 Thread Kishon Vijay Abraham I
commit 091876cc355d ("phy: ti: j721e-wiz: Add support for WIZ module
present in TI J721E SoC") modeled the internal clocks depending on the
subnodes that are populated in device tree. However recent discussions
in the mailing list [1] suggested to just add #clock cells in the parent
DT node and model the clocks within the driver.

Model the mux clocks without device tree input for AM64x SoC. Don't
remove the earlier design since DT nodes for J7200 and J721e are already
upstreamed.

[1] -> http://lore.kernel.org/r/20210108025943.ga1790...@robh.at.kernel.org

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/phy/ti/phy-j721e-wiz.c | 144 +++--
 1 file changed, 139 insertions(+), 5 deletions(-)

diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c
index 2706e7be0c28..f9299dcdbdb7 100644
--- a/drivers/phy/ti/phy-j721e-wiz.c
+++ b/drivers/phy/ti/phy-j721e-wiz.c
@@ -7,6 +7,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -27,6 +28,10 @@
 #define WIZ_SERDES_TYPEC   0x410
 #define WIZ_LANECTL(n) (0x480 + (0x40 * (n)))
 
+#define WIZ_MAX_INPUT_CLOCKS   4
+/* To include mux clocks, divider clocks and gate clocks */
+#define WIZ_MAX_OUTPUT_CLOCKS  32
+
 #define WIZ_MAX_LANES  4
 #define WIZ_MUX_NUM_CLOCKS 3
 #define WIZ_DIV_NUM_CLOCKS_16G 2
@@ -52,6 +57,13 @@ enum wiz_refclk_div_sel {
CMN_REFCLK1_DIG_DIV,
 };
 
+enum wiz_clock_input {
+   WIZ_CORE_REFCLK,
+   WIZ_EXT_REFCLK,
+   WIZ_CORE_REFCLK1,
+   WIZ_EXT_REFCLK1,
+};
+
 static const struct reg_field por_en = REG_FIELD(WIZ_SERDES_CTRL, 31, 31);
 static const struct reg_field phy_reset_n = REG_FIELD(WIZ_SERDES_RST, 31, 31);
 static const struct reg_field pll1_refclk_mux_sel =
@@ -70,6 +82,11 @@ static const struct reg_field pma_cmn_refclk_dig_div =
REG_FIELD(WIZ_SERDES_TOP_CTRL, 26, 27);
 static const struct reg_field pma_cmn_refclk1_dig_div =
REG_FIELD(WIZ_SERDES_TOP_CTRL, 24, 25);
+static const char * const output_clk_names[] = {
+   [TI_WIZ_PLL0_REFCLK] = "pll0-refclk",
+   [TI_WIZ_PLL1_REFCLK] = "pll1-refclk",
+   [TI_WIZ_REFCLK_DIG] = "refclk-dig",
+};
 
 static const struct reg_field p_enable[WIZ_MAX_LANES] = {
REG_FIELD(WIZ_LANECTL(0), 30, 31),
@@ -130,8 +147,10 @@ struct wiz_clk_divider {
 #define to_wiz_clk_div(_hw) container_of(_hw, struct wiz_clk_divider, hw)
 
 struct wiz_clk_mux_sel {
-   u32 table[4];
+   u32 table[WIZ_MAX_INPUT_CLOCKS];
const char  *node_name;
+   u32 num_parents;
+   u32 parents[WIZ_MAX_INPUT_CLOCKS];
 };
 
 struct wiz_clk_div_sel {
@@ -164,14 +183,20 @@ static const struct wiz_clk_mux_sel clk_mux_sel_10g[] = {
 * Mux value to be configured for each of the input clocks
 * in the order populated in device tree
 */
+   .num_parents = 2,
+   .parents = { WIZ_CORE_REFCLK, WIZ_EXT_REFCLK },
.table = { 1, 0 },
.node_name = "pll0-refclk",
},
{
+   .num_parents = 2,
+   .parents = { WIZ_CORE_REFCLK, WIZ_EXT_REFCLK },
.table = { 1, 0 },
.node_name = "pll1-refclk",
},
{
+   .num_parents = 2,
+   .parents = { WIZ_CORE_REFCLK, WIZ_EXT_REFCLK },
.table = { 1, 0 },
.node_name = "refclk-dig",
},
@@ -232,6 +257,9 @@ struct wiz {
struct gpio_desc*gpio_typec_dir;
int typec_dir_delay;
u32 lane_phy_type[WIZ_MAX_LANES];
+   struct clk  *input_clks[WIZ_MAX_INPUT_CLOCKS];
+   struct clk  *output_clks[WIZ_MAX_OUTPUT_CLOCKS];
+   struct clk_onecell_data clk_data;
 };
 
 static int wiz_reset(struct wiz *wiz)
@@ -469,8 +497,69 @@ static const struct clk_ops wiz_clk_mux_ops = {
.get_parent = wiz_clk_mux_get_parent,
 };
 
-static int wiz_mux_clk_register(struct wiz *wiz, struct device_node *node,
-   struct regmap_field *field, const u32 *table)
+static int wiz_mux_clk_register(struct wiz *wiz, struct regmap_field *field,
+   const struct wiz_clk_mux_sel *mux_sel, int 
clk_index)
+{
+   struct device *dev = wiz->dev;
+   struct clk_init_data *init;
+   const char **parent_names;
+   unsigned int num_parents;
+   struct wiz_clk_mux *mux;
+   char clk_name[100];
+   struct clk *clk;
+   int ret = 0, i;
+
+   mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
+   if (!mux)
+   return -ENOMEM;
+
+   num_parents = mux_sel->num_parents;
+
+   parent_names = kzalloc((sizeof(char *) * num_p

[PATCH v3 3/6] phy: ti: j721e-wiz: Configure full rate divider for AM64

2021-03-10 Thread Kishon Vijay Abraham I
The frequency of the txmclk between PCIe and SERDES has
changed to 250MHz from 500MHz. Configure full rate divider
for AM64 accordingly.

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/phy/ti/phy-j721e-wiz.c | 39 +++---
 1 file changed, 36 insertions(+), 3 deletions(-)

diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c
index 1a4e09a394a8..2706e7be0c28 100644
--- a/drivers/phy/ti/phy-j721e-wiz.c
+++ b/drivers/phy/ti/phy-j721e-wiz.c
@@ -101,6 +101,13 @@ static const struct reg_field 
p_standard_mode[WIZ_MAX_LANES] = {
REG_FIELD(WIZ_LANECTL(3), 24, 25),
 };
 
+static const struct reg_field p0_fullrt_div[WIZ_MAX_LANES] = {
+   REG_FIELD(WIZ_LANECTL(0), 22, 23),
+   REG_FIELD(WIZ_LANECTL(1), 22, 23),
+   REG_FIELD(WIZ_LANECTL(2), 22, 23),
+   REG_FIELD(WIZ_LANECTL(3), 22, 23),
+};
+
 static const struct reg_field typec_ln10_swap =
REG_FIELD(WIZ_SERDES_TYPEC, 30, 30);
 
@@ -191,6 +198,7 @@ static const struct wiz_clk_div_sel clk_div_sel[] = {
 enum wiz_type {
J721E_WIZ_16G,
J721E_WIZ_10G,
+   AM64_WIZ_10G,
 };
 
 #define WIZ_TYPEC_DIR_DEBOUNCE_MIN 100 /* ms */
@@ -208,6 +216,7 @@ struct wiz {
struct regmap_field *p_align[WIZ_MAX_LANES];
struct regmap_field *p_raw_auto_start[WIZ_MAX_LANES];
struct regmap_field *p_standard_mode[WIZ_MAX_LANES];
+   struct regmap_field *p0_fullrt_div[WIZ_MAX_LANES];
struct regmap_field *pma_cmn_refclk_int_mode;
struct regmap_field *pma_cmn_refclk_mode;
struct regmap_field *pma_cmn_refclk_dig_div;
@@ -373,7 +382,7 @@ static int wiz_regfield_init(struct wiz *wiz)
return PTR_ERR(wiz->mux_sel_field[PLL1_REFCLK]);
}
 
-   if (wiz->type == J721E_WIZ_10G)
+   if (wiz->type == J721E_WIZ_10G || wiz->type == AM64_WIZ_10G)
wiz->mux_sel_field[REFCLK_DIG] =
devm_regmap_field_alloc(dev, regmap,
refclk_dig_sel_10g);
@@ -417,6 +426,12 @@ static int wiz_regfield_init(struct wiz *wiz)
i);
return PTR_ERR(wiz->p_standard_mode[i]);
}
+
+   wiz->p0_fullrt_div[i] = devm_regmap_field_alloc(dev, regmap, 
p0_fullrt_div[i]);
+   if (IS_ERR(wiz->p0_fullrt_div[i])) {
+   dev_err(dev, "P%d_FULLRT_DIV reg field init failed\n", 
i);
+   return PTR_ERR(wiz->p0_fullrt_div[i]);
+   }
}
 
wiz->typec_ln10_swap = devm_regmap_field_alloc(dev, regmap,
@@ -718,6 +733,17 @@ static int wiz_phy_reset_assert(struct 
reset_controller_dev *rcdev,
return ret;
 }
 
+static int wiz_phy_fullrt_div(struct wiz *wiz, int lane)
+{
+   if (wiz->type != AM64_WIZ_10G)
+   return 0;
+
+   if (wiz->lane_phy_type[lane] == PHY_TYPE_PCIE)
+   return regmap_field_write(wiz->p0_fullrt_div[lane], 0x1);
+
+   return 0;
+}
+
 static int wiz_phy_reset_deassert(struct reset_controller_dev *rcdev,
  unsigned long id)
 {
@@ -741,6 +767,10 @@ static int wiz_phy_reset_deassert(struct 
reset_controller_dev *rcdev,
return ret;
}
 
+   ret = wiz_phy_fullrt_div(wiz, id - 1);
+   if (ret)
+   return ret;
+
if (wiz->lane_phy_type[id - 1] == PHY_TYPE_DP)
ret = regmap_field_write(wiz->p_enable[id - 1], P_ENABLE);
else
@@ -768,6 +798,9 @@ static const struct of_device_id wiz_id_table[] = {
{
.compatible = "ti,j721e-wiz-10g", .data = (void *)J721E_WIZ_10G
},
+   {
+   .compatible = "ti,am64-wiz-10g", .data = (void *)AM64_WIZ_10G
+   },
{}
 };
 MODULE_DEVICE_TABLE(of, wiz_id_table);
@@ -899,14 +932,14 @@ static int wiz_probe(struct platform_device *pdev)
wiz->dev = dev;
wiz->regmap = regmap;
wiz->num_lanes = num_lanes;
-   if (wiz->type == J721E_WIZ_10G)
+   if (wiz->type == J721E_WIZ_10G || wiz->type == AM64_WIZ_10G)
wiz->clk_mux_sel = clk_mux_sel_10g;
else
wiz->clk_mux_sel = clk_mux_sel_16g;
 
wiz->clk_div_sel = clk_div_sel;
 
-   if (wiz->type == J721E_WIZ_10G)
+   if (wiz->type == J721E_WIZ_10G || wiz->type == AM64_WIZ_10G)
wiz->clk_div_sel_num = WIZ_DIV_NUM_CLOCKS_10G;
else
wiz->clk_div_sel_num = WIZ_DIV_NUM_CLOCKS_16G;
-- 
2.17.1



[PATCH v3 2/6] phy: ti: j721e-wiz: Delete "clk_div_sel" clk provider during cleanup

2021-03-10 Thread Kishon Vijay Abraham I
commit 091876cc355d ("phy: ti: j721e-wiz: Add support for WIZ module
present in TI J721E SoC") modeled both MUX clocks and DIVIDER clocks in
wiz. However during cleanup, it removed only the MUX clock provider.
Remove the DIVIDER clock provider here.

Fixes: 091876cc355d ("phy: ti: j721e-wiz: Add support for WIZ module present in 
TI J721E SoC")
Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/phy/ti/phy-j721e-wiz.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c
index 956a93d96d9b..1a4e09a394a8 100644
--- a/drivers/phy/ti/phy-j721e-wiz.c
+++ b/drivers/phy/ti/phy-j721e-wiz.c
@@ -608,6 +608,12 @@ static void wiz_clock_cleanup(struct wiz *wiz, struct 
device_node *node)
of_clk_del_provider(clk_node);
of_node_put(clk_node);
}
+
+   for (i = 0; i < wiz->clk_div_sel_num; i++) {
+   clk_node = of_get_child_by_name(node, clk_div_sel[i].node_name);
+   of_clk_del_provider(clk_node);
+   of_node_put(clk_node);
+   }
 }
 
 static int wiz_clock_init(struct wiz *wiz, struct device_node *node)
-- 
2.17.1



[PATCH v3 1/6] phy: ti: j721e-wiz: Remove "regmap_field" from wiz_clk_{mux|div}_sel

2021-03-10 Thread Kishon Vijay Abraham I
Both "struct wiz_clk_div_sel" and "struct wiz_clk_mux_sel" are static
data that is common for all wiz instances. Including
"struct regmap_field" for each of the wiz instances can yield undesirable
results. Move "struct regmap_field" out of "struct wiz_clk_div_sel" and
"struct wiz_clk_mux_sel" and make them point to constant data.

So far no issues are observed since both these structures are not
accessed outside the probe.

Signed-off-by: Kishon Vijay Abraham I 
---
 drivers/phy/ti/phy-j721e-wiz.c | 75 +++---
 1 file changed, 34 insertions(+), 41 deletions(-)

diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c
index c9cfafe89cbf..956a93d96d9b 100644
--- a/drivers/phy/ti/phy-j721e-wiz.c
+++ b/drivers/phy/ti/phy-j721e-wiz.c
@@ -107,7 +107,7 @@ static const struct reg_field typec_ln10_swap =
 struct wiz_clk_mux {
struct clk_hw   hw;
struct regmap_field *field;
-   u32 *table;
+   const u32   *table;
struct clk_init_dataclk_data;
 };
 
@@ -123,18 +123,16 @@ struct wiz_clk_divider {
 #define to_wiz_clk_div(_hw) container_of(_hw, struct wiz_clk_divider, hw)
 
 struct wiz_clk_mux_sel {
-   struct regmap_field *field;
u32 table[4];
const char  *node_name;
 };
 
 struct wiz_clk_div_sel {
-   struct regmap_field *field;
-   const struct clk_div_table  *table;
+   const struct clk_div_table *table;
const char  *node_name;
 };
 
-static struct wiz_clk_mux_sel clk_mux_sel_16g[] = {
+static const struct wiz_clk_mux_sel clk_mux_sel_16g[] = {
{
/*
 * Mux value to be configured for each of the input clocks
@@ -153,7 +151,7 @@ static struct wiz_clk_mux_sel clk_mux_sel_16g[] = {
},
 };
 
-static struct wiz_clk_mux_sel clk_mux_sel_10g[] = {
+static const struct wiz_clk_mux_sel clk_mux_sel_10g[] = {
{
/*
 * Mux value to be configured for each of the input clocks
@@ -179,7 +177,7 @@ static const struct clk_div_table clk_div_table[] = {
{ .val = 3, .div = 8, },
 };
 
-static struct wiz_clk_div_sel clk_div_sel[] = {
+static const struct wiz_clk_div_sel clk_div_sel[] = {
{
.table = clk_div_table,
.node_name = "cmn-refclk-dig-div",
@@ -201,8 +199,8 @@ enum wiz_type {
 struct wiz {
struct regmap   *regmap;
enum wiz_type   type;
-   struct wiz_clk_mux_sel  *clk_mux_sel;
-   struct wiz_clk_div_sel  *clk_div_sel;
+   const struct wiz_clk_mux_sel *clk_mux_sel;
+   const struct wiz_clk_div_sel *clk_div_sel;
unsigned intclk_div_sel_num;
struct regmap_field *por_en;
struct regmap_field *phy_reset_n;
@@ -214,6 +212,8 @@ struct wiz {
struct regmap_field *pma_cmn_refclk_mode;
struct regmap_field *pma_cmn_refclk_dig_div;
struct regmap_field *pma_cmn_refclk1_dig_div;
+   struct regmap_field *mux_sel_field[WIZ_MUX_NUM_CLOCKS];
+   struct regmap_field *div_sel_field[WIZ_DIV_NUM_CLOCKS_16G];
struct regmap_field *typec_ln10_swap;
 
struct device   *dev;
@@ -310,8 +310,6 @@ static int wiz_init(struct wiz *wiz)
 
 static int wiz_regfield_init(struct wiz *wiz)
 {
-   struct wiz_clk_mux_sel *clk_mux_sel;
-   struct wiz_clk_div_sel *clk_div_sel;
struct regmap *regmap = wiz->regmap;
int num_lanes = wiz->num_lanes;
struct device *dev = wiz->dev;
@@ -344,54 +342,49 @@ static int wiz_regfield_init(struct wiz *wiz)
return PTR_ERR(wiz->pma_cmn_refclk_mode);
}
 
-   clk_div_sel = >clk_div_sel[CMN_REFCLK_DIG_DIV];
-   clk_div_sel->field = devm_regmap_field_alloc(dev, regmap,
-pma_cmn_refclk_dig_div);
-   if (IS_ERR(clk_div_sel->field)) {
+   wiz->div_sel_field[CMN_REFCLK_DIG_DIV] =
+   devm_regmap_field_alloc(dev, regmap, pma_cmn_refclk_dig_div);
+   if (IS_ERR(wiz->div_sel_field[CMN_REFCLK_DIG_DIV])) {
dev_err(dev, "PMA_CMN_REFCLK_DIG_DIV reg field init failed\n");
-   return PTR_ERR(clk_div_sel->field);
+   return PTR_ERR(wiz->div_sel_field[CMN_REFCLK_DIG_DIV]);
}
 
if (wiz->type == J721E_WIZ_16G) {
-   clk_div_sel = >clk_div_sel[CMN_REFCLK1_DIG_DIV];
-   clk_div_sel->field =
+   wiz->div_sel_field[CMN_REFCLK1_DIG_DIV] =
devm_regmap_field_alloc(dev, regmap,
pma_cmn_refclk1_dig_div);
-   if (IS_ERR(clk_div_sel->field)) {
+   if (IS_ERR(wiz->div_sel_field[CMN_REFCLK1_DIG_DIV]))

  1   2   3   4   5   6   7   8   9   10   >