* Re: [PATCH v6 02/14] clk: qcom: Add rcg ops to return floor value closest to the requested rate
From: Ritesh Harjani @ 2016-11-09 11:53 UTC (permalink / raw)
To: Stephen Boyd
Cc: ulf.hansson, linux-mmc, adrian.hunter, shawn.lin, devicetree,
linux-clk, david.brown, andy.gross, linux-arm-msm, georgi.djakov,
alex.lemberg, mateusz.nowak, Yuliy.Izrailov, asutoshd, kdorfman,
david.griego, stummala, venkatg, rnayak, pramod.gurav
In-Reply-To: <20161108230217.GM16026@codeaurora.org>
Hi Stephen,
Thanks for the review.
On 11/9/2016 4:32 AM, Stephen Boyd wrote:
> On 11/07, Ritesh Harjani wrote:
>> diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h
>> index b904c33..1b3e8d2 100644
>> --- a/drivers/clk/qcom/clk-rcg.h
>> +++ b/drivers/clk/qcom/clk-rcg.h
>> @@ -173,6 +173,7 @@ struct clk_rcg2 {
>> #define to_clk_rcg2(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg2, clkr)
>>
>> extern const struct clk_ops clk_rcg2_ops;
>> +extern const struct clk_ops clk_rcg2_floor_ops;
>> extern const struct clk_ops clk_rcg2_shared_ops;
>> extern const struct clk_ops clk_edp_pixel_ops;
>> extern const struct clk_ops clk_byte_ops;
>> diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
>> index a071bba..04433a6 100644
>> --- a/drivers/clk/qcom/clk-rcg2.c
>> +++ b/drivers/clk/qcom/clk-rcg2.c
>> @@ -47,6 +47,11 @@
>> #define N_REG 0xc
>> #define D_REG 0x10
>>
>> +enum {
>> + FLOOR,
>> + CEIL,
>> +};
>
> Give it a name.
Yes, sure. I will keep it as freq_policy.
>
>> +
>> static int clk_rcg2_is_enabled(struct clk_hw *hw)
>> {
>> struct clk_rcg2 *rcg = to_clk_rcg2(hw);
>> @@ -176,15 +181,25 @@ static int clk_rcg2_set_parent(struct clk_hw *hw, u8 index)
>> return calc_rate(parent_rate, m, n, mode, hid_div);
>> }
>>
>> -static int _freq_tbl_determine_rate(struct clk_hw *hw,
>> - const struct freq_tbl *f, struct clk_rate_request *req)
>> +static int _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f,
>> + struct clk_rate_request *req, bool match)
>
> Use the enum please. Also name it something besides match.
> policy?
Sure. (freq_policy)
>
>> {
>> unsigned long clk_flags, rate = req->rate;
>> struct clk_hw *p;
>> struct clk_rcg2 *rcg = to_clk_rcg2(hw);
>> int index;
>>
>> - f = qcom_find_freq(f, rate);
>> + switch (match) {
>> + case FLOOR:
>> + f = qcom_find_freq_floor(f, rate);
>> + break;
>> + case CEIL:
>> + f = qcom_find_freq(f, rate);
>> + break;
>> + default:
>> + return -EINVAL;
>> + };
>> +
>> if (!f)
>> return -EINVAL;
>>
>> diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c
>> index fffcbaf..cf6b87f 100644
>> --- a/drivers/clk/qcom/common.c
>> +++ b/drivers/clk/qcom/common.c
>> @@ -46,6 +46,32 @@ struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, unsigned long rate)
>> }
>> EXPORT_SYMBOL_GPL(qcom_find_freq);
>>
>> +const
>> +struct freq_tbl *qcom_find_freq_floor(const struct freq_tbl *f,
>
> We can't put const and struct on the same line?
Ok sure.
>
>> + unsigned long rate)
>> +{
>> + int size = 0;
>> +
>> + if (!f)
>> + return NULL;
>> +
>> + /*
>> + * The freq table has entries in the ascending order of frequencies
>> + * To find the floor for a given frequency, we need to do a reverse
>> + * lookup of the table
>> + */
>> + for (; f->freq; f++, size++)
>> + ;
>> +
>> + for (f--; size; f--, size--)
>> + if (rate >= f->freq)
>> + return f;
>
> I don't understand why we can't do this while iterating through
> the table. We shouldn't need to size up the frequency table first.
>
> const struct freq_tbl *best = NULL;
>
> for ( ; f->freq; f++) {
> if (rate >= f->freq)
> best = f->freq;
> else
> break;
> }
>
> return best;
>
Yes, will do above change.
>> +
>> + /* could not find any rates lower than *rate* */
>
>> + return NULL;
>> +}
>> +EXPORT_SYMBOL_GPL(qcom_find_freq_floor);
>
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply
* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
From: liviu.dudau-5wv7dgnIgG8 @ 2016-11-09 11:39 UTC (permalink / raw)
To: zhichang.yuan
Cc: catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, bhelgaas-hpIqsD4AKlfQT0dZR+AlfA,
mark.rutland-5wv7dgnIgG8, olof-nZhT3qVonbNeoWH0uzbU5w,
arnd-r2nGTMty4D4,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
lorenzo.pieralisi-5wv7dgnIgG8,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linuxarm-hv44wF8Li93QT0dZR+AlfA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-pci-u79uwXL29TY76Z2rM5mHXA,
linux-serial-u79uwXL29TY76Z2rM5mHXA, minyard-HInyCGIudOg,
benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r,
zourongrong-Re5JQEeQqe8AvxtiuMwx3w,
john.garry-hv44wF8Li93QT0dZR+AlfA,
gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA,
zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w, kantyzc-9Onoh4P/yGk,
xuwei5-C8/M+/jPZTeaMJb+Lgu22Q
In-Reply-To: <1478576829-112707-3-git-send-email-yuanzhichang-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
On Tue, Nov 08, 2016 at 11:47:08AM +0800, zhichang.yuan wrote:
> This patch solves two issues:
> 1) parse and get the right I/O range from DTS node whose parent does not
> define the corresponding ranges property;
>
> There are some special ISA/LPC devices that work on a specific I/O range where
> it is not correct to specify a ranges property in DTS parent node as cpu
> addresses translated from DTS node are only for memory space on some
> architectures, such as Arm64. Without the parent 'ranges' property, current
> of_translate_address() return an error.
> Here we add a fixup function, of_get_isa_indirect_io(). During the OF address
> translation, this fixup will be called to check the 'reg' address to be
> translating is for those sepcial ISA/LPC devices and get the I/O range
> directly from the 'reg' property.
>
> 2) eliminate the I/O range conflict risk with PCI/PCIE leagecy I/O device;
>
> The current __of_address_to_resource() always translates the I/O range to PIO.
> But this processing is not suitable for our ISA/LPC devices whose I/O range is
> not cpu address(Arnd had stressed this in his comments on V2,V3 patch-set).
> Here, we bypass the mapping between cpu address and PIO for the special
> ISA/LPC devices. But to drive these ISA/LPC devices, a I/O port address below
> PCIBIOS_MIN_IO is needed by in*/out*(). Which means there is conflict risk
> between I/O range of [0, PCIBIOS_MIN_IO) and PCI/PCIE legacy I/O range of [0,
> IO_SPACE_LIMIT).
> To avoid the I/O conflict, this patch reserve the I/O range below
> PCIBIOS_MIN_IO.
>
> Signed-off-by: zhichang.yuan <yuanzhichang-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
> ---
> .../arm/hisilicon/hisilicon-low-pin-count.txt | 31 ++++++++++++
> arch/arm64/include/asm/io.h | 6 +++
> arch/arm64/kernel/extio.c | 25 ++++++++++
> drivers/of/address.c | 56 +++++++++++++++++++++-
> drivers/pci/pci.c | 6 +--
> include/linux/of_address.h | 17 +++++++
> include/linux/pci.h | 8 ++++
> 7 files changed, 145 insertions(+), 4 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
>
> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
> new file mode 100644
> index 0000000..13c8ddd
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
> @@ -0,0 +1,31 @@
> +Hisilicon Hip06 low-pin-count device
> + Usually LPC controller is part of PCI host bridge, so the legacy ISA ports
> + locate on LPC bus can be accessed direclty. But some SoCs have independent
> + LPC controller, and access the legacy ports by triggering LPC I/O cycles.
> + Hisilicon Hip06 implements this LPC device.
> +
> +Required properties:
> +- compatible: should be "hisilicon,low-pin-count"
> +- #address-cells: must be 2 which stick to the ISA/EISA binding doc.
> +- #size-cells: must be 1 which stick to the ISA/EISA binding doc.
> +- reg: base memory range where the register set of this device is mapped.
> +
> +Note:
> + The node name before '@' must be "isa" to represent the binding stick to the
> + ISA/EISA binding specification.
> +
> +Example:
> +
> +isa@a01b0000 {
> + compatible = "hisilicom,low-pin-count";
> + #address-cells = <2>;
> + #size-cells = <1>;
> + reg = <0x0 0xa01b0000 0x0 0x1000>;
> +
> + ipmi0: bt@e4 {
> + compatible = "ipmi-bt";
> + device_type = "ipmi";
> + reg = <0x01 0xe4 0x04>;
> + status = "disabled";
> + };
> +};
This documentation file needs to be part of the next patch. It has nothing to do with
what you are trying to fix here.
> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
> index 136735d..c26b7cc 100644
> --- a/arch/arm64/include/asm/io.h
> +++ b/arch/arm64/include/asm/io.h
> @@ -175,6 +175,12 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
> #define outsl outsl
>
> DECLARE_EXTIO(l, u32)
> +
> +#define indirect_io_enabled indirect_io_enabled
> +extern bool indirect_io_enabled(void);
> +
> +#define addr_is_indirect_io addr_is_indirect_io
> +extern int addr_is_indirect_io(u64 taddr);
> #endif
>
>
> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
> index 647b3fa..3d45fa8 100644
> --- a/arch/arm64/kernel/extio.c
> +++ b/arch/arm64/kernel/extio.c
> @@ -19,6 +19,31 @@
>
> struct extio_ops *arm64_extio_ops;
>
> +/**
> + * indirect_io_enabled - check whether indirectIO is enabled.
> + * arm64_extio_ops will be set only when indirectIO mechanism had been
> + * initialized.
> + *
> + * Returns true when indirectIO is enabled.
> + */
> +bool indirect_io_enabled(void)
> +{
> + return arm64_extio_ops ? true : false;
> +}
> +
> +/**
> + * addr_is_indirect_io - check whether the input taddr is for indirectIO.
> + * @taddr: the io address to be checked.
> + *
> + * Returns 1 when taddr is in the range; otherwise return 0.
> + */
> +int addr_is_indirect_io(u64 taddr)
> +{
> + if (arm64_extio_ops->start > taddr || arm64_extio_ops->end < taddr)
start >= taddr ?
> + return 0;
> +
> + return 1;
> +}
>
> BUILD_EXTIO(b, u8)
>
> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 02b2903..cc2a05d 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct device_node *np)
> return false;
> }
>
> +
> +/*
> + * of_isa_indirect_io - get the IO address from some isa reg property value.
> + * For some isa/lpc devices, no ranges property in ancestor node.
> + * The device addresses are described directly in their regs property.
> + * This fixup function will be called to get the IO address of isa/lpc
> + * devices when the normal of_translation failed.
> + *
> + * @parent: points to the parent dts node;
> + * @bus: points to the of_bus which can be used to parse address;
> + * @addr: the address from reg property;
> + * @na: the address cell counter of @addr;
> + * @presult: store the address paresed from @addr;
> + *
> + * return 1 when successfully get the I/O address;
> + * 0 will return for some failures.
Bah, you are returning a signed int, why 0 for failure? Return a negative value with
error codes. Otherwise change the return value into a bool.
> + */
> +static int of_get_isa_indirect_io(struct device_node *parent,
> + struct of_bus *bus, __be32 *addr,
> + int na, u64 *presult)
> +{
> + unsigned int flags;
> + unsigned int rlen;
> +
> + /* whether support indirectIO */
> + if (!indirect_io_enabled())
> + return 0;
> +
> + if (!of_bus_isa_match(parent))
> + return 0;
> +
> + flags = bus->get_flags(addr);
> + if (!(flags & IORESOURCE_IO))
> + return 0;
> +
> + /* there is ranges property, apply the normal translation directly. */
s/there is ranges/if we have a 'ranges'/
> + if (of_get_property(parent, "ranges", &rlen))
> + return 0;
> +
> + *presult = of_read_number(addr + 1, na - 1);
> + /* this fixup is only valid for specific I/O range. */
> + return addr_is_indirect_io(*presult);
> +}
> +
> static int of_translate_one(struct device_node *parent, struct of_bus *bus,
> struct of_bus *pbus, __be32 *addr,
> int na, int ns, int pna, const char *rprop)
> @@ -595,6 +639,15 @@ static u64 __of_translate_address(struct device_node *dev,
> result = of_read_number(addr, na);
> break;
> }
> + /*
> + * For indirectIO device which has no ranges property, get
> + * the address from reg directly.
> + */
> + if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
> + pr_debug("isa indirectIO matched(%s)..addr = 0x%llx\n",
> + of_node_full_name(dev), result);
> + break;
> + }
>
> /* Get new parent bus and counts */
> pbus = of_match_bus(parent);
> @@ -688,8 +741,9 @@ static int __of_address_to_resource(struct device_node *dev,
> if (taddr == OF_BAD_ADDR)
> return -EINVAL;
> memset(r, 0, sizeof(struct resource));
> - if (flags & IORESOURCE_IO) {
> + if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
> unsigned long port;
> +
> port = pci_address_to_pio(taddr);
> if (port == (unsigned long)-1)
> return -EINVAL;
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index ba34907..1a08511 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -3263,7 +3263,7 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
>
> #ifdef PCI_IOBASE
> struct io_range *range;
> - resource_size_t allocated_size = 0;
> + resource_size_t allocated_size = PCIBIOS_MIN_IO;
>
> /* check if the range hasn't been previously recorded */
> spin_lock(&io_range_lock);
> @@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned long pio)
>
> #ifdef PCI_IOBASE
> struct io_range *range;
> - resource_size_t allocated_size = 0;
> + resource_size_t allocated_size = PCIBIOS_MIN_IO;
Have you checked that pci_pio_to_address still returns valid values after this? I know that
you are trying to take into account PCIBIOS_MIN_IO limit when allocating reserving the IO ranges,
but the values added in the io_range_list are still starting from zero, no from PCIBIOS_MIN_IO,
so the calculation of the address in this function could return negative values casted to pci_addr_t.
Maybe you want to adjust the range->start value in pci_register_io_range() as well to have it
offset by PCIBIOS_MIN_IO as well.
Best regards,
Liviu
>
> if (pio > IO_SPACE_LIMIT)
> return address;
> @@ -3335,7 +3335,7 @@ unsigned long __weak pci_address_to_pio(phys_addr_t address)
> {
> #ifdef PCI_IOBASE
> struct io_range *res;
> - resource_size_t offset = 0;
> + resource_size_t offset = PCIBIOS_MIN_IO;
> unsigned long addr = -1;
>
> spin_lock(&io_range_lock);
> diff --git a/include/linux/of_address.h b/include/linux/of_address.h
> index 3786473..deec469 100644
> --- a/include/linux/of_address.h
> +++ b/include/linux/of_address.h
> @@ -24,6 +24,23 @@ struct of_pci_range {
> #define for_each_of_pci_range(parser, range) \
> for (; of_pci_range_parser_one(parser, range);)
>
> +
> +#ifndef indirect_io_enabled
> +#define indirect_io_enabled indirect_io_enabled
> +static inline bool indirect_io_enabled(void)
> +{
> + return false;
> +}
> +#endif
> +
> +#ifndef addr_is_indirect_io
> +#define addr_is_indirect_io addr_is_indirect_io
> +static inline int addr_is_indirect_io(u64 taddr)
> +{
> + return 0;
> +}
> +#endif
> +
> /* Translate a DMA address from device space to CPU space */
> extern u64 of_translate_dma_address(struct device_node *dev,
> const __be32 *in_addr);
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 0e49f70..7f6bbb6 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct pci_bus *bus)
> /* provide the legacy pci_dma_* API */
> #include <linux/pci-dma-compat.h>
>
> +/*
> + * define this macro here to refrain from compilation error for some
> + * platforms. Please keep this macro at the end of this header file.
> + */
> +#ifndef PCIBIOS_MIN_IO
> +#define PCIBIOS_MIN_IO 0
> +#endif
> +
> #endif /* LINUX_PCI_H */
> --
> 1.9.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
====================
| I would like to |
| fix the world, |
| but they're not |
| giving me the |
\ source code! /
---------------
¯\_(ツ)_/¯
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] ata: xgene: Enable NCQ support for APM X-Gene SATA controller hardware v1.1
From: Rameshwar Sahu @ 2016-11-09 11:39 UTC (permalink / raw)
To: Olof Johansson, tj, Arnd Bergmann
Cc: Devicetree List, mlangsdo, linux-scsi, Jon Masters,
Rameshwar Prasad Sahu, patches, linux-ide, linux-arm
In-Reply-To: <1476962064-8775-1-git-send-email-rsahu@apm.com>
Hi Olof/Tejun,
On Thu, Oct 20, 2016 at 4:44 PM, Rameshwar Prasad Sahu <rsahu@apm.com> wrote:
>
> This patch enables NCQ support for APM X-Gene SATA controller
> hardware v1.1 that was broken with hardware v1.0.
>
> Signed-off-by: Rameshwar Prasad Sahu <rsahu@apm.com>
> ---
> drivers/ata/ahci_xgene.c | 14 ++++++++------
> 1 files changed, 8 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c
> index 73b19b2..8b88be9 100644
> --- a/drivers/ata/ahci_xgene.c
> +++ b/drivers/ata/ahci_xgene.c
> @@ -87,6 +87,7 @@
>
> enum xgene_ahci_version {
> XGENE_AHCI_V1 = 1,
> + XGENE_AHCI_V1_1,
> XGENE_AHCI_V2,
> };
>
> @@ -734,6 +735,7 @@ static struct scsi_host_template ahci_platform_sht = {
> #ifdef CONFIG_ACPI
> static const struct acpi_device_id xgene_ahci_acpi_match[] = {
> { "APMC0D0D", XGENE_AHCI_V1},
> + { "APMC0D67", XGENE_AHCI_V1_1},
> { "APMC0D32", XGENE_AHCI_V2},
> {},
> };
> @@ -742,6 +744,7 @@ MODULE_DEVICE_TABLE(acpi, xgene_ahci_acpi_match);
>
> static const struct of_device_id xgene_ahci_of_match[] = {
> {.compatible = "apm,xgene-ahci", .data = (void *) XGENE_AHCI_V1},
> + {.compatible = "apm,xgene-ahci-v1-1", .data = (void *) XGENE_AHCI_V1_1},
> {.compatible = "apm,xgene-ahci-v2", .data = (void *) XGENE_AHCI_V2},
> {},
> };
> @@ -755,8 +758,7 @@ static int xgene_ahci_probe(struct platform_device *pdev)
> struct resource *res;
> const struct of_device_id *of_devid;
> enum xgene_ahci_version version = XGENE_AHCI_V1;
> - const struct ata_port_info *ppi[] = { &xgene_ahci_v1_port_info,
> - &xgene_ahci_v2_port_info };
> + const struct ata_port_info *ppi;
> int rc;
>
> hpriv = ahci_platform_get_resources(pdev);
> @@ -821,8 +823,6 @@ static int xgene_ahci_probe(struct platform_device *pdev)
> dev_warn(&pdev->dev, "%s: Error reading device info. Assume version1\n",
> __func__);
> version = XGENE_AHCI_V1;
> - } else if (info->valid & ACPI_VALID_CID) {
> - version = XGENE_AHCI_V2;
> }
> }
> }
> @@ -858,18 +858,20 @@ skip_clk_phy:
>
> switch (version) {
> case XGENE_AHCI_V1:
> + ppi = &xgene_ahci_v1_port_info;
> hpriv->flags = AHCI_HFLAG_NO_NCQ;
> break;
> case XGENE_AHCI_V2:
> + ppi = &xgene_ahci_v2_port_info;
> hpriv->flags |= AHCI_HFLAG_YES_FBS;
> hpriv->irq_handler = xgene_ahci_irq_intr;
> break;
> default:
> + ppi = &xgene_ahci_v1_port_info;
> break;
> }
>
> - rc = ahci_platform_init_host(pdev, hpriv, ppi[version - 1],
> - &ahci_platform_sht);
> + rc = ahci_platform_init_host(pdev, hpriv, ppi, &ahci_platform_sht);
> if (rc)
> goto disable_resources;
>
> --
> 1.7.1
Any comment on above patch ??
^ permalink raw reply
* Re: [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
From: John Garry @ 2016-11-09 11:29 UTC (permalink / raw)
To: Arnd Bergmann, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Cc: Will Deacon, mark.rutland-5wv7dgnIgG8,
catalin.marinas-5wv7dgnIgG8,
gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA,
linux-pci-u79uwXL29TY76Z2rM5mHXA, liviu.dudau-5wv7dgnIgG8,
linuxarm-hv44wF8Li93QT0dZR+AlfA, lorenzo.pieralisi-5wv7dgnIgG8,
minyard-HInyCGIudOg, xuwei5-C8/M+/jPZTeaMJb+Lgu22Q,
linux-serial-u79uwXL29TY76Z2rM5mHXA,
benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
zhichang.yuan02-Re5JQEeQqe8AvxtiuMwx3w,
olof-nZhT3qVonbNeoWH0uzbU5w, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
bhelgaas-hpIqsD4AKlfQT0dZR+AlfA, kantyzc-9Onoh4P/yGk,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, zhichang.yuan,
zourongrong-Re5JQEeQqe8AvxtiuMwx3w
In-Reply-To: <2479288.4UmF9SBrq1@wuerfel>
On 08/11/2016 22:35, Arnd Bergmann wrote:
> On Tuesday, November 8, 2016 4:49:49 PM CET Will Deacon wrote:
>> On Tue, Nov 08, 2016 at 04:33:44PM +0000, John Garry wrote:
>>> On 08/11/2016 16:12, Will Deacon wrote:
>>>> On Tue, Nov 08, 2016 at 11:47:07AM +0800, zhichang.yuan wrote:
>
>>>> Is there no way to make this slightly more generic, so that it can be
>>>> re-used elsewhere? For example, if struct extio_ops was common, then
>>>> you could have the singleton (which maybe should be an interval tree?),
>>>> type definition, setter function and the BUILD_EXTIO invocations
>>>> somewhere generic, rather than squirelled away in the arch backend.
>>>>
>>> The concern would be that some architecture which uses generic higher-level
>>> ISA accessor ops, but have IO space, could be affected.
>>
>> You're already adding a Kconfig symbol for this stuff, so you can keep
>> that if you don't want it on other architectures. I'm just arguing that
>> plumbing drivers directly into arch code via arm64_set_extops is not
>> something I'm particularly fond of, especially when it looks like it
>> could be avoided with a small amount of effort.
>
> Agreed, I initially suggested putting this into arch/arm64/, but there isn't
> really a reason why it couldn't just live in lib/ with the header file
> bits moved to include/asm-generic/io.h which we already use.
>
Right, Zhichang will check the logistics of this. The generic io.h is
quite clean, so as long as you don't mind new build switches of this
nature being added, it should be ok; and we'll plan on moving extio.h
into include/asm-generic as well.
Cheers,
John
> Arnd
>
> .
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
From: Mark Rutland @ 2016-11-09 11:20 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: zhichang.yuan, catalin.marinas, will.deacon, robh+dt, bhelgaas,
olof, arnd, linux-arm-kernel, lorenzo.pieralisi, linux-kernel,
linuxarm, devicetree, linux-pci, linux-serial, minyard,
liviu.dudau, zourongrong, john.garry, gabriele.paoloni,
zhichang.yuan02, kantyzc, xuwei5, marc.zyngier
In-Reply-To: <1478646779.7430.66.camel@kernel.crashing.org>
On Wed, Nov 09, 2016 at 10:12:59AM +1100, Benjamin Herrenschmidt wrote:
> On Tue, 2016-11-08 at 11:49 +0000, Mark Rutland wrote:
> > I believe that we could theoretically have multiple independent LPC/ISA
> > busses, as is possible with PCI on !x86 systems. If the current ISA code
> > assumes a singleton bus, I think that's something that needs to be fixed
> > up more generically.
> >
> > I don't see why we should need any architecture-specific code here. Why
> > can we not fix up the ISA bus code in drivers/of/address.c such that it
> > handles multiple ISA bus instances, and translates all sub-device
> > addresses relative to the specific bus instance?
>
> What in that code prevents that today ?
It appears I was mistaken w.r.t. the singleton comment. We can already
translate MMIO->MMIO addresses per-instance (in the presence of a ranges
property).
The big change would be to handle !MMIO translations, for which we'd
need a runtime registry of ISA bus instance to find the relevant
accessor ops and instance-specific data.
Thanks,
Mark.
^ permalink raw reply
* [PATCH v2] mtd/spi-nor: Add SPI memory controllers for Aspeed SoCs
From: Cédric Le Goater @ 2016-11-09 10:42 UTC (permalink / raw)
To: linux-mtd
Cc: Mark Rutland, Boris Brezillon, devicetree, Richard Weinberger,
Marek Vasut, Rob Herring, Joel Stanley, Cyrille Pitchen,
Brian Norris, David Woodhouse, Cédric Le Goater
This driver adds mtd support for spi-nor attached to either or both of
the Firmware Memory Controller or the SPI Flash Controller (AST2400
only).
The SMC controllers on the Aspeed AST2500 SoC are very similar to the
ones found on the AST2400. The differences are on the number of
supported flash modules and their default mappings in the SoC address
space.
The Aspeed AST2500 has one SPI controller for the BMC firmware and two
for the host firmware. All controllers have now the same set of
registers compatible with the AST2400 FMC controller and the legacy
'SMC' controller is fully gone.
Each controller has a memory range on which it maps its flash module
slaves. Each slave is assigned a memory window for its mapping that
can be changed at bootime with the Segment Address Register.
Each SPI flash slave can then be accessed in two modes: Command and
User. When in User mode, accesses to the memory segment of the slaves
are translated in SPI transfers. When in Command mode, the HW
generates the SPI commands automatically and the memory segment is
accessed as if doing a MMIO.
Currently, only the User mode is supported. Command mode needs a
little more work to check that the memory window on the AHB bus fits
the module size.
Based on previous work from Milton D. Miller II <miltonm@us.ibm.com>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
Tested on:
* OpenPOWER Palmetto (AST2400) with
FMC controller : n25q256a
SPI controller : mx25l25635e and n25q512ax3
* Evaluation board (AST2500) with
FMC controller : w25q256
SPI controller : w25q256
* OpenPOWER Witherspoon (AST2500) with
FMC controller : mx25l25635e * 2
SPI controller : mx66l1g45g
Changes since v2:
- added a set4b ops to handle difference in the controllers
- simplified the IO routines
- prepared for fast read using dummy cycles
Work in progress:
- read optimization using higher SPI clock frequencies
- command mode to direct reads from AHB
- DMA support
.../devicetree/bindings/mtd/aspeed-smc.txt | 72 ++
drivers/mtd/spi-nor/Kconfig | 12 +
drivers/mtd/spi-nor/Makefile | 1 +
drivers/mtd/spi-nor/aspeed-smc.c | 783 +++++++++++++++++++++
4 files changed, 868 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mtd/aspeed-smc.txt
create mode 100644 drivers/mtd/spi-nor/aspeed-smc.c
diff --git a/Documentation/devicetree/bindings/mtd/aspeed-smc.txt b/Documentation/devicetree/bindings/mtd/aspeed-smc.txt
new file mode 100644
index 000000000000..7516b0c01fcf
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/aspeed-smc.txt
@@ -0,0 +1,72 @@
+* Aspeed Static Memory controller
+* Aspeed SPI Flash Controller
+
+The Static memory controller in the ast2400 supports 5 chip selects
+each can be attached to NAND, parallel NOR, or SPI NOR attached flash.
+The Firmware Memory Controller in the ast2500 supports 3 chip selects,
+two of which are always in SPI-NOR mode and the third can be SPI-NOR
+or parallel flash. The SPI flash controller in the ast2400 supports
+one of 2 chip selects selected by pinmux. The two SPI flash
+controllers in the ast2500 each support two chip selects.
+
+Required properties:
+ - compatible : Should be one of
+ "aspeed,ast2400-fmc" for the AST2400 Static Memory Controller
+ "aspeed,ast2400-smc" for the AST2400 SPI Flash Controller
+ "aspeed,ast2500-fmc" for the AST2500 Firmware SPI Memory Controller
+ "aspeed,ast2500-smc" for the AST2500 SPI Flash Controllers
+ - reg : the first contains the control register location and length,
+ the second contains the memory window mapping address and length
+ - #address-cells : must be 1 corresponding to chip select child binding
+ - #size-cells : must be 0 corresponding to chip select child binding
+
+Optional properties:
+ - interrupts : Should contain the interrupt for the dma device if an fmc
+
+The child nodes are the SPI Flash modules which must have a compatible
+property as specified in bindings/mtd/jedec,spi-nor.txt
+
+Optionally, the child node can contain properties for SPI mode (may be
+ignored):
+ - spi-max-frequency - (optional) max frequency of spi bus
+
+
+Example:
+fmc: fmc@1e620000 {
+ compatible = "aspeed,ast2400-fmc";
+ reg = < 0x1e620000 0x94
+ 0x20000000 0x02000000
+ 0x22000000 0x02000000 >;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <19>;
+ flash@0 {
+ reg = < 0 >;
+ compatible = "jedec,spi-nor" ;
+ /* spi-max-frequency = <>; */
+ /* m25p,fast-read; */
+ #address-cells = <1>;
+ #size-cells = <1>;
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ boot@0 {
+ label = "boot-loader";
+ reg = < 0 0x8000 >;
+ };
+ image@8000 {
+ label = "kernel-image";
+ reg = < 0x8000 0x1f8000 >;
+ };
+ };
+ };
+ flash@1 {
+ reg = < 1 >;
+ compatible = "jedec,spi-nor" ;
+ label = "alt";
+ /* spi-max-frequency = <>; */
+ status = "fail";
+ /* m25p,fast-read; */
+ };
+};
diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
index 4a682ee0f632..96148600fdab 100644
--- a/drivers/mtd/spi-nor/Kconfig
+++ b/drivers/mtd/spi-nor/Kconfig
@@ -76,4 +76,16 @@ config SPI_NXP_SPIFI
Flash. Enable this option if you have a device with a SPIFI
controller and want to access the Flash as a mtd device.
+config ASPEED_FLASH_SPI
+ tristate "Aspeed flash controllers in SPI mode"
+ depends on HAS_IOMEM && OF
+ depends on ARCH_ASPEED || COMPILE_TEST
+ # IO_SPACE_LIMIT must be equivalent to (~0UL)
+ depends on !NEED_MACH_IO_H
+ help
+ This enables support for the New Static Memory Controller
+ (FMC) in the Aspeed SoCs (AST2400 and AST2500) when attached
+ to SPI nor chips, and support for the SPI Memory controller
+ (SPI) for the BIOS.
+
endif # MTD_SPI_NOR
diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index 121695e83542..c3174ebc45c2 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -4,4 +4,5 @@ obj-$(CONFIG_SPI_CADENCE_QUADSPI) += cadence-quadspi.o
obj-$(CONFIG_SPI_FSL_QUADSPI) += fsl-quadspi.o
obj-$(CONFIG_SPI_HISI_SFC) += hisi-sfc.o
obj-$(CONFIG_MTD_MT81xx_NOR) += mtk-quadspi.o
+obj-$(CONFIG_ASPEED_FLASH_SPI) += aspeed-smc.o
obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi.o
diff --git a/drivers/mtd/spi-nor/aspeed-smc.c b/drivers/mtd/spi-nor/aspeed-smc.c
new file mode 100644
index 000000000000..30662daf89ca
--- /dev/null
+++ b/drivers/mtd/spi-nor/aspeed-smc.c
@@ -0,0 +1,783 @@
+/*
+ * ASPEED Static Memory Controller driver
+ *
+ * Copyright (c) 2015-2016, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/bug.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/spi-nor.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/sysfs.h>
+
+#define DEVICE_NAME "aspeed-smc"
+
+/*
+ * In user mode all data bytes read or written to the chip decode address
+ * range are transferred to or from the SPI bus. The range is treated as a
+ * fifo of arbitratry 1, 2, or 4 byte width but each write has to be aligned
+ * to its size. The address within the multiple 8kB range is ignored when
+ * sending bytes to the SPI bus.
+ *
+ * On the arm architecture, as of Linux version 4.3, memcpy_fromio and
+ * memcpy_toio on little endian targets use the optimized memcpy routines
+ * that were designed for well behavied memory storage. These routines
+ * have a stutter if the source and destination are not both word aligned,
+ * once with a duplicate access to the source after aligning to the
+ * destination to a word boundary, and again with a duplicate access to
+ * the source when the final byte count is not word aligned.
+ *
+ * When writing or reading the fifo this stutter discards data or sends
+ * too much data to the fifo and can not be used by this driver.
+ *
+ * While the low level io string routines that implement the insl family do
+ * the desired accesses and memory increments, the cross architecture io
+ * macros make them essentially impossible to use on a memory mapped address
+ * instead of a a token from the call to iomap of an io port.
+ *
+ * These fifo routines use readl and friends to a constant io port and update
+ * the memory buffer pointer and count via explicit code. The final updates
+ * to len are optimistically suppressed.
+ */
+static int aspeed_smc_read_from_ahb(void *buf, const void __iomem *src,
+ size_t len)
+{
+ if ((((unsigned long)src | (unsigned long)buf | len) & 3) == 0) {
+ while (len > 3) {
+ *(u32 *)buf = readl(src);
+ buf += 4;
+ src += 4;
+ len -= 4;
+ }
+ }
+
+ while (len--) {
+ *(u8 *)buf = readb(src);
+ buf += 1;
+ src += 1;
+ }
+ return 0;
+}
+
+static int aspeed_smc_write_to_ahb(void __iomem *dst, const void *buf,
+ size_t len)
+{
+ if ((((unsigned long)dst | (unsigned long)buf | len) & 3) == 0) {
+ while (len > 3) {
+ u32 val = *(u32 *)buf;
+
+ writel(val, dst);
+ buf += 4;
+ dst += 4;
+ len -= 4;
+ }
+ }
+
+ while (len--) {
+ u8 val = *(u8 *)buf;
+
+ writeb(val, dst);
+ buf += 1;
+ dst += 1;
+ }
+ return 0;
+}
+
+enum smc_flash_type {
+ smc_type_nor = 0, /* controller connected to nor flash */
+ smc_type_nand = 1, /* controller connected to nand flash */
+ smc_type_spi = 2, /* controller connected to spi flash */
+};
+
+struct aspeed_smc_chip;
+
+struct aspeed_smc_info {
+ u32 maxsize; /* maximum size of 1 chip window */
+ u8 nce; /* number of chip enables */
+ u8 maxwidth; /* max width of spi bus */
+ bool hastype; /* flash type field exists in cfg reg */
+ u8 we0; /* shift for write enable bit for ce 0 */
+ u8 ctl0; /* offset in regs of ctl for ce 0 */
+ u8 time; /* offset in regs of timing */
+ u8 misc; /* offset in regs of misc settings */
+
+ void (*set_4b)(struct aspeed_smc_chip *chip);
+};
+
+static void aspeed_smc_chip_set_4b_smc_2400(struct aspeed_smc_chip *chip);
+static void aspeed_smc_chip_set_4b(struct aspeed_smc_chip *chip);
+
+static const struct aspeed_smc_info fmc_2400_info = {
+ .maxsize = 64 * 1024 * 1024,
+ .nce = 5,
+ .maxwidth = 4,
+ .hastype = true,
+ .we0 = 16,
+ .ctl0 = 0x10,
+ .time = 0x94,
+ .misc = 0x54,
+ .set_4b = aspeed_smc_chip_set_4b,
+};
+
+static const struct aspeed_smc_info smc_2400_info = {
+ .maxsize = 64 * 1024 * 1024,
+ .nce = 1,
+ .maxwidth = 2,
+ .hastype = false,
+ .we0 = 0,
+ .ctl0 = 0x04,
+ .time = 0x14,
+ .misc = 0x10,
+ .set_4b = aspeed_smc_chip_set_4b_smc_2400,
+};
+
+static const struct aspeed_smc_info fmc_2500_info = {
+ .maxsize = 256 * 1024 * 1024,
+ .nce = 3,
+ .maxwidth = 2,
+ .hastype = true,
+ .we0 = 16,
+ .ctl0 = 0x10,
+ .time = 0x94,
+ .misc = 0x54,
+ .set_4b = aspeed_smc_chip_set_4b,
+};
+
+static const struct aspeed_smc_info smc_2500_info = {
+ .maxsize = 128 * 1024 * 1024,
+ .nce = 2,
+ .maxwidth = 2,
+ .hastype = false,
+ .we0 = 16,
+ .ctl0 = 0x10,
+ .time = 0x94,
+ .misc = 0x54,
+ .set_4b = aspeed_smc_chip_set_4b,
+};
+
+enum smc_ctl_reg_value {
+ smc_base, /* base value without mode for other commands */
+ smc_read, /* command reg for (maybe fast) reads */
+ smc_write, /* command reg for writes with timings */
+ smc_num_ctl_reg_values /* last value to get count of commands */
+};
+
+struct aspeed_smc_controller;
+
+struct aspeed_smc_chip {
+ int cs;
+ struct aspeed_smc_controller *controller;
+ __le32 __iomem *ctl; /* control register */
+ void __iomem *base; /* base of chip window */
+ __le32 ctl_val[smc_num_ctl_reg_values]; /* controls with timing */
+ enum smc_flash_type type; /* what type of flash */
+ struct spi_nor nor;
+};
+
+struct aspeed_smc_controller {
+ struct device *dev;
+
+ struct mutex mutex; /* controller access mutex */
+ const struct aspeed_smc_info *info; /* type info of controller */
+ void __iomem *regs; /* controller registers */
+ void __iomem *windows; /* per-chip windows resource */
+
+ struct aspeed_smc_chip *chips[0]; /* pointers to attached chips */
+};
+
+/*
+ * SPI Flash Configuration Register (AST2400 SPI)
+ */
+#define CONFIG_REG 0x0
+#define CONFIG_ENABLE_CE_INACTIVE BIT(1)
+#define CONFIG_WRITE BIT(0)
+
+/*
+ * SPI Flash Configuration Register (AST2500 SPI)
+ * Type setting Register (AST2500 FMC and AST2400 FMC)
+ */
+#define TYPE_SETTING_REG 0x0
+#define CONFIG_DISABLE_LEGACY BIT(31) /* 1 on AST2500 FMC */
+
+#define CONFIG_CE2_WRITE BIT(18)
+#define CONFIG_CE1_WRITE BIT(17)
+#define CONFIG_CE0_WRITE BIT(16)
+
+#define CONFIG_CE2_TYPE BIT(4) /* FMC only */
+#define CONFIG_CE1_TYPE BIT(2) /* FMC only */
+#define CONFIG_CE0_TYPE BIT(0) /* FMC only */
+
+/*
+ * CE Control Register (AST2500 SPI,FMC and AST2400 FMC)
+ */
+#define CE_CONTROL_REG 0x4
+#define CE2_ENABLE_CE_INACTIVE BIT(10)
+#define CE1_ENABLE_CE_INACTIVE BIT(9)
+#define CE0_ENABLE_CE_INACTIVE BIT(8)
+#define CE2_CONTROL_EXTENDED BIT(2)
+#define CE1_CONTROL_EXTENDED BIT(1)
+#define CE0_CONTROL_EXTENDED BIT(0)
+
+/* CE0 Control Register (depends on the controller type) */
+#define CONTROL_SPI_AAF_MODE BIT(31)
+#define CONTROL_SPI_IO_MODE_MASK GENMASK(30, 28)
+#define CONTROL_SPI_IO_DUAL_DATA BIT(29)
+#define CONTROL_SPI_IO_DUAL_ADDR_DATA (BIT(29) | BIT(28))
+#define CONTROL_SPI_IO_QUAD_DATA BIT(30)
+#define CONTROL_SPI_IO_QUAD_ADDR_DATA (BIT(30) | BIT(28))
+#define CONTROL_SPI_CE_INACTIVE_SHIFT 24
+#define CONTROL_SPI_CE_INACTIVE_MASK GENMASK(27, CONTROL_SPI_CE_INACTIVE_SHIFT)
+/* 0 = 16T ... 15 = 1T T=HCLK */
+#define CONTROL_SPI_COMMAND_SHIFT 16
+#define CONTROL_SPI_DUMMY_CYCLE_COMMAND_OUTPUT BIT(15)
+#define CONTROL_SPI_IO_DUMMY_CYCLES_HI BIT(14)
+#define CONTROL_SPI_IO_DUMMY_CYCLES_HI_SHIFT 14
+#define CONTROL_SPI_IO_ADDRESS_4B BIT(13) /* AST2400 SPI */
+#define CONTROL_SPI_CLK_DIV4 BIT(13) /* others */
+#define CONTROL_SPI_RW_MERGE BIT(12)
+#define CONTROL_SPI_IO_DUMMY_CYCLES_LO_SHIFT 6
+#define CONTROL_SPI_IO_DUMMY_CYCLES_LO GENMASK(7, \
+ CONTROL_SPI_IO_DUMMY_CYCLES_LO_SHIFT)
+#define CONTROL_SPI_IO_DUMMY_CYCLES_MASK (CONTROL_SPI_IO_DUMMY_CYCLES_HI | \
+ CONTROL_SPI_IO_DUMMY_CYCLES_LO)
+#define CONTROL_SPI_IO_DUMMY_CYCLES_SET(dummy) \
+ (((((dummy) >> 2) & 0x1) << CONTROL_SPI_IO_DUMMY_CYCLES_HI_SHIFT) | \
+ (((dummy) & 0x3) << CONTROL_SPI_IO_DUMMY_CYCLES_LO_SHIFT))
+
+#define CONTROL_SPI_CLOCK_FREQ_SEL_SHIFT 8
+#define CONTROL_SPI_CLOCK_FREQ_SEL_MASK GENMASK(11, \
+ CONTROL_SPI_CLOCK_FREQ_SEL_SHIFT)
+#define CONTROL_SPI_LSB_FIRST BIT(5)
+#define CONTROL_SPI_CLOCK_MODE_3 BIT(4)
+#define CONTROL_SPI_IN_DUAL_DATA BIT(3)
+#define CONTROL_SPI_CE_STOP_ACTIVE_CONTROL BIT(2)
+#define CONTROL_SPI_COMMAND_MODE_MASK GENMASK(1, 0)
+#define CONTROL_SPI_COMMAND_MODE_NORMAL (0)
+#define CONTROL_SPI_COMMAND_MODE_FREAD (1)
+#define CONTROL_SPI_COMMAND_MODE_WRITE (2)
+#define CONTROL_SPI_COMMAND_MODE_USER (3)
+
+#define CONTROL_SPI_KEEP_MASK (CONTROL_SPI_AAF_MODE | \
+ CONTROL_SPI_CE_INACTIVE_MASK | CONTROL_SPI_CLK_DIV4 | \
+ CONTROL_SPI_IO_DUMMY_CYCLES_MASK | CONTROL_SPI_CLOCK_FREQ_SEL_MASK | \
+ CONTROL_SPI_LSB_FIRST | CONTROL_SPI_CLOCK_MODE_3)
+
+/* Segment Address Registers */
+#define SEGMENT_ADDR_REG0 0x30
+#define SEGMENT_ADDR_START(_r) ((((_r) >> 16) & 0xFF) << 23)
+#define SEGMENT_ADDR_END(_r) ((((_r) >> 24) & 0xFF) << 23)
+
+static u32 spi_control_fill_opcode(u8 opcode)
+{
+ return ((u32)(opcode)) << CONTROL_SPI_COMMAND_SHIFT;
+}
+
+static inline u32 aspeed_smc_chip_write_bit(struct aspeed_smc_chip *chip)
+{
+ return ((u32)1 << (chip->controller->info->we0 + chip->cs));
+}
+
+static void aspeed_smc_chip_check_config(struct aspeed_smc_chip *chip)
+{
+ struct aspeed_smc_controller *controller = chip->controller;
+ u32 reg;
+
+ reg = readl(controller->regs + CONFIG_REG);
+
+ if (!(reg & aspeed_smc_chip_write_bit(chip))) {
+ dev_dbg(controller->dev,
+ "config write is not set ! @%p: 0x%08x\n",
+ controller->regs + CONFIG_REG, reg);
+ reg |= aspeed_smc_chip_write_bit(chip);
+ writel(reg, controller->regs + CONFIG_REG);
+ }
+}
+
+static void aspeed_smc_start_user(struct spi_nor *nor)
+{
+ struct aspeed_smc_chip *chip = nor->priv;
+ u32 ctl = chip->ctl_val[smc_base];
+
+ /*
+ * When the chip is controlled in user mode, we need write
+ * access to send the opcodes to it. So check the config.
+ */
+ aspeed_smc_chip_check_config(chip);
+
+ ctl |= CONTROL_SPI_COMMAND_MODE_USER |
+ CONTROL_SPI_CE_STOP_ACTIVE_CONTROL;
+ writel(ctl, chip->ctl);
+
+ ctl &= ~CONTROL_SPI_CE_STOP_ACTIVE_CONTROL;
+ writel(ctl, chip->ctl);
+}
+
+static void aspeed_smc_stop_user(struct spi_nor *nor)
+{
+ struct aspeed_smc_chip *chip = nor->priv;
+
+ u32 ctl = chip->ctl_val[smc_read];
+ u32 ctl2 = ctl | CONTROL_SPI_COMMAND_MODE_USER |
+ CONTROL_SPI_CE_STOP_ACTIVE_CONTROL;
+
+ writel(ctl2, chip->ctl); /* stop user CE control */
+ writel(ctl, chip->ctl); /* default to fread or read */
+}
+
+static int aspeed_smc_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
+{
+ struct aspeed_smc_chip *chip = nor->priv;
+
+ mutex_lock(&chip->controller->mutex);
+
+ aspeed_smc_start_user(nor);
+ aspeed_smc_write_to_ahb(chip->base, &opcode, 1);
+ aspeed_smc_read_from_ahb(buf, chip->base, len);
+ aspeed_smc_stop_user(nor);
+
+ mutex_unlock(&chip->controller->mutex);
+
+ return 0;
+}
+
+static int aspeed_smc_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
+ int len)
+{
+ struct aspeed_smc_chip *chip = nor->priv;
+
+ mutex_lock(&chip->controller->mutex);
+
+ aspeed_smc_start_user(nor);
+ aspeed_smc_write_to_ahb(chip->base, &opcode, 1);
+ aspeed_smc_write_to_ahb(chip->base, buf, len);
+ aspeed_smc_stop_user(nor);
+
+ mutex_unlock(&chip->controller->mutex);
+
+ return 0;
+}
+
+static void aspeed_smc_send_cmd_addr(struct spi_nor *nor, u8 cmd, u32 addr)
+{
+ struct aspeed_smc_chip *chip = nor->priv;
+ __be32 temp;
+ u32 cmdaddr;
+
+ switch (nor->addr_width) {
+ default:
+ WARN_ONCE(1, "Unexpected address width %u, defaulting to 3\n",
+ nor->addr_width);
+ /* FALLTHROUGH */
+ case 3:
+ cmdaddr = addr & 0xFFFFFF;
+
+ cmdaddr |= (u32)cmd << 24;
+
+ temp = cpu_to_be32(cmdaddr);
+ aspeed_smc_write_to_ahb(chip->base, &temp, 4);
+ break;
+ case 4:
+ temp = cpu_to_be32(addr);
+ aspeed_smc_write_to_ahb(chip->base, &cmd, 1);
+ aspeed_smc_write_to_ahb(chip->base, &temp, 4);
+ break;
+ }
+}
+
+static ssize_t aspeed_smc_read_user(struct spi_nor *nor, loff_t from,
+ size_t len, u_char *read_buf)
+{
+ struct aspeed_smc_chip *chip = nor->priv;
+
+ mutex_lock(&chip->controller->mutex);
+
+ aspeed_smc_start_user(nor);
+ aspeed_smc_send_cmd_addr(nor, nor->read_opcode, from);
+ aspeed_smc_read_from_ahb(read_buf, chip->base, len);
+ aspeed_smc_stop_user(nor);
+
+ mutex_unlock(&chip->controller->mutex);
+
+ return len;
+}
+
+static ssize_t aspeed_smc_write_user(struct spi_nor *nor, loff_t to, size_t len,
+ const u_char *write_buf)
+{
+ struct aspeed_smc_chip *chip = nor->priv;
+
+ mutex_lock(&chip->controller->mutex);
+
+ aspeed_smc_start_user(nor);
+ aspeed_smc_send_cmd_addr(nor, nor->program_opcode, to);
+ aspeed_smc_write_to_ahb(chip->base, write_buf, len);
+ aspeed_smc_stop_user(nor);
+
+ mutex_unlock(&chip->controller->mutex);
+
+ return len;
+}
+
+static int aspeed_smc_remove(struct platform_device *dev)
+{
+ struct aspeed_smc_chip *chip;
+ struct aspeed_smc_controller *controller = platform_get_drvdata(dev);
+ int n;
+
+ for (n = 0; n < controller->info->nce; n++) {
+ chip = controller->chips[n];
+ if (chip)
+ mtd_device_unregister(&chip->nor.mtd);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id aspeed_smc_matches[] = {
+ { .compatible = "aspeed,ast2400-fmc", .data = &fmc_2400_info },
+ { .compatible = "aspeed,ast2400-smc", .data = &smc_2400_info },
+ { .compatible = "aspeed,ast2500-fmc", .data = &fmc_2500_info },
+ { .compatible = "aspeed,ast2500-smc", .data = &smc_2500_info },
+ { }
+};
+MODULE_DEVICE_TABLE(of, aspeed_smc_matches);
+
+static struct platform_device *
+of_platform_device_create_or_find(struct device_node *child,
+ struct device *parent)
+{
+ struct platform_device *cdev;
+
+ cdev = of_platform_device_create(child, NULL, parent);
+ if (!cdev)
+ cdev = of_find_device_by_node(child);
+ return cdev;
+}
+
+static void __iomem *window_start(struct aspeed_smc_controller *controller,
+ struct resource *r, unsigned int n)
+{
+ u32 offset = 0;
+ u32 reg;
+
+ if (controller->info->nce > 1) {
+ reg = readl(controller->regs + SEGMENT_ADDR_REG0 + n * 4);
+
+ if (SEGMENT_ADDR_START(reg) >= SEGMENT_ADDR_END(reg))
+ return NULL;
+
+ offset = SEGMENT_ADDR_START(reg) - r->start;
+ }
+
+ return controller->windows + offset;
+}
+
+static void aspeed_smc_chip_enable_write(struct aspeed_smc_chip *chip)
+{
+ struct aspeed_smc_controller *controller = chip->controller;
+ u32 reg;
+
+ reg = readl(controller->regs + CONFIG_REG);
+
+ reg |= aspeed_smc_chip_write_bit(chip);
+ writel(reg, controller->regs + CONFIG_REG);
+}
+
+static void aspeed_smc_chip_set_type(struct aspeed_smc_chip *chip, int type)
+{
+ struct aspeed_smc_controller *controller = chip->controller;
+ u32 reg;
+
+ reg = readl(controller->regs + CONFIG_REG);
+
+ chip->type = type;
+
+ reg &= ~(3 << (chip->cs * 2));
+ reg |= chip->type << (chip->cs * 2);
+ writel(reg, controller->regs + CONFIG_REG);
+}
+
+/*
+ * The AST2500 FMC and AST2400 FMC flash controllers should be
+ * strapped by hardware, or autodetected, but the AST2500 SPI flash
+ * needs to be set.
+ */
+static void aspeed_smc_chip_set_4b(struct aspeed_smc_chip *chip)
+{
+ struct aspeed_smc_controller *controller = chip->controller;
+ u32 reg;
+
+ if (chip->controller->info == &smc_2500_info) {
+ reg = readl(controller->regs + CE_CONTROL_REG);
+ reg |= 1 << chip->cs;
+ writel(reg, controller->regs + CE_CONTROL_REG);
+ }
+}
+
+/*
+ * The AST2400 SPI flash controller does not have a CE Control
+ * register. It uses the CE0 control register to set 4Byte mode at the
+ * controller level.
+ */
+static void aspeed_smc_chip_set_4b_smc_2400(struct aspeed_smc_chip *chip)
+{
+ chip->ctl_val[smc_base] |= CONTROL_SPI_IO_ADDRESS_4B;
+ chip->ctl_val[smc_read] |= CONTROL_SPI_IO_ADDRESS_4B;
+}
+
+static int aspeed_smc_chip_setup_init(struct aspeed_smc_chip *chip,
+ struct resource *r)
+{
+ struct aspeed_smc_controller *controller = chip->controller;
+ const struct aspeed_smc_info *info = controller->info;
+ u32 reg, base_reg;
+
+ /*
+ * Always turn on the write enable bit to allow opcodes to be
+ * sent in user mode.
+ */
+ aspeed_smc_chip_enable_write(chip);
+
+ /* The driver only supports SPI type flash for the moment */
+ if (info->hastype)
+ aspeed_smc_chip_set_type(chip, smc_type_spi);
+
+ /*
+ * Configure chip base address in memory
+ */
+ chip->base = window_start(controller, r, chip->cs);
+ if (!chip->base) {
+ dev_warn(chip->nor.dev, "CE segment window closed.\n");
+ return -1;
+ }
+
+ /*
+ * Read the existing control register to get basic values.
+ *
+ * XXX This register probably needs more sanitation.
+ *
+ * Do we need support for mode 3 vs mode 0 clock phasing?
+ */
+ reg = readl(chip->ctl);
+ dev_dbg(controller->dev, "control register: %08x\n", reg);
+
+ base_reg = reg & CONTROL_SPI_KEEP_MASK;
+ if (base_reg != reg) {
+ dev_info(controller->dev,
+ "control register changed to: %08x\n",
+ base_reg);
+ }
+ chip->ctl_val[smc_base] = base_reg;
+
+ /*
+ * Retain the prior value of the control register as the
+ * default if it was normal access mode. Otherwise start with
+ * the sanitized base value set to read mode.
+ */
+ if ((reg & CONTROL_SPI_COMMAND_MODE_MASK) ==
+ CONTROL_SPI_COMMAND_MODE_NORMAL)
+ chip->ctl_val[smc_read] = reg;
+ else
+ chip->ctl_val[smc_read] = chip->ctl_val[smc_base] |
+ CONTROL_SPI_COMMAND_MODE_NORMAL;
+
+ dev_dbg(controller->dev, "default control register: %08x\n",
+ chip->ctl_val[smc_read]);
+ return 0;
+}
+
+static int aspeed_smc_chip_setup_finish(struct aspeed_smc_chip *chip)
+{
+ struct aspeed_smc_controller *controller = chip->controller;
+ const struct aspeed_smc_info *info = controller->info;
+ u32 cmd;
+
+ if (chip->nor.addr_width == 4 && info->set_4b)
+ info->set_4b(chip);
+
+ /*
+ * base mode has not been optimized yet. use it for writes.
+ */
+ chip->ctl_val[smc_write] = chip->ctl_val[smc_base] |
+ spi_control_fill_opcode(chip->nor.program_opcode) |
+ CONTROL_SPI_COMMAND_MODE_WRITE;
+
+ dev_dbg(controller->dev, "write control register: %08x\n",
+ chip->ctl_val[smc_write]);
+
+ /*
+ * XXX TODO
+ * Adjust clocks if fast read and write are supported.
+ * Interpret spi-nor flags to adjust controller settings.
+ * Check if resource size big enough for detected chip and
+ * add support assisted (normal or fast-) read and dma.
+ */
+ switch (chip->nor.flash_read) {
+ case SPI_NOR_NORMAL:
+ cmd = CONTROL_SPI_COMMAND_MODE_NORMAL;
+ break;
+ case SPI_NOR_FAST:
+ cmd = CONTROL_SPI_COMMAND_MODE_FREAD;
+ break;
+ default:
+ dev_err(chip->nor.dev, "unsupported SPI read mode\n");
+ return -EINVAL;
+ }
+
+ chip->ctl_val[smc_read] |= cmd |
+ CONTROL_SPI_IO_DUMMY_CYCLES_SET(chip->nor.read_dummy / 8);
+
+ dev_dbg(controller->dev, "base control register: %08x\n",
+ chip->ctl_val[smc_read]);
+ return 0;
+}
+
+static int aspeed_smc_probe(struct platform_device *pdev)
+{
+ struct aspeed_smc_controller *controller;
+ const struct of_device_id *match;
+ const struct aspeed_smc_info *info;
+ struct resource *r;
+ struct device_node *child;
+ int err = 0;
+ unsigned int n;
+
+ match = of_match_device(aspeed_smc_matches, &pdev->dev);
+ if (!match || !match->data)
+ return -ENODEV;
+ info = match->data;
+
+ controller = devm_kzalloc(&pdev->dev, sizeof(*controller) +
+ info->nce * sizeof(controller->chips[0]), GFP_KERNEL);
+ if (!controller)
+ return -ENOMEM;
+ controller->info = info;
+
+ mutex_init(&controller->mutex);
+ platform_set_drvdata(pdev, controller);
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ controller->regs = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(controller->regs))
+ return PTR_ERR(controller->regs);
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ controller->windows = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(controller->windows))
+ return PTR_ERR(controller->windows);
+
+ controller->dev = &pdev->dev;
+
+ /* The pinmux or bootloader will disable the legacy mode controller */
+
+ /*
+ * XXX Need to add arbitration to the SMC (BIOS) controller if access
+ * is shared by the host.
+ */
+ for_each_available_child_of_node(controller->dev->of_node, child) {
+ struct platform_device *cdev;
+ struct aspeed_smc_chip *chip;
+
+ /* This version does not support nand or nor flash devices. */
+ if (!of_device_is_compatible(child, "jedec,spi-nor"))
+ continue;
+
+ /*
+ * create a platform device from the of node. If the device
+ * already was created (eg from a prior bind/unbind cycle)
+ * reuse it.
+ *
+ * The creating the device node for the child here allows its
+ * use for error reporting via dev_err below.
+ */
+ cdev = of_platform_device_create_or_find(child,
+ controller->dev);
+ if (!cdev)
+ continue;
+
+ err = of_property_read_u32(child, "reg", &n);
+ if (err == -EINVAL && info->nce == 1)
+ n = 0;
+ else if (err || n >= info->nce)
+ continue;
+ if (controller->chips[n]) {
+ dev_err(&cdev->dev,
+ "chip-id %u already in use in use by %s\n",
+ n, dev_name(controller->chips[n]->nor.dev));
+ continue;
+ }
+
+ chip = devm_kzalloc(controller->dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
+ continue;
+ chip->controller = controller;
+ chip->ctl = controller->regs + info->ctl0 + n * 4;
+ chip->cs = n;
+
+ chip->nor.dev = &cdev->dev;
+ chip->nor.priv = chip;
+ spi_nor_set_flash_node(&chip->nor, child);
+ chip->nor.mtd.name = of_get_property(child, "label", NULL);
+ chip->nor.read = aspeed_smc_read_user;
+ chip->nor.write = aspeed_smc_write_user;
+ chip->nor.read_reg = aspeed_smc_read_reg;
+ chip->nor.write_reg = aspeed_smc_write_reg;
+
+ err = aspeed_smc_chip_setup_init(chip, r);
+ if (err)
+ continue;
+
+ /*
+ * XXX Add support for SPI_NOR_QUAD and SPI_NOR_DUAL attach
+ * when board support is present as determined by of property.
+ */
+ err = spi_nor_scan(&chip->nor, NULL, SPI_NOR_NORMAL);
+ if (err)
+ continue;
+
+ err = aspeed_smc_chip_setup_finish(chip);
+ if (err)
+ continue;
+
+ err = mtd_device_register(&chip->nor.mtd, NULL, 0);
+ if (err)
+ continue;
+ controller->chips[n] = chip;
+ }
+
+ /* Were any children registered? */
+ for (n = 0; n < info->nce; n++)
+ if (controller->chips[n])
+ break;
+
+ if (n == info->nce)
+ return -ENODEV;
+
+ return 0;
+}
+
+static struct platform_driver aspeed_smc_driver = {
+ .probe = aspeed_smc_probe,
+ .remove = aspeed_smc_remove,
+ .driver = {
+ .name = DEVICE_NAME,
+ .of_match_table = aspeed_smc_matches,
+ }
+};
+
+module_platform_driver(aspeed_smc_driver);
+
+MODULE_DESCRIPTION("ASPEED Static Memory Controller Driver");
+MODULE_AUTHOR("Milton Miller");
+MODULE_LICENSE("GPL v2");
--
2.7.4
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related
* Re: [PATCH v3 2/3] PCI: qcom: add support to msm8996 PCIE controller
From: Vivek Gautam @ 2016-11-09 10:37 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: svarbanov, Bjorn Helgaas, linux-pci, Rob Herring, Mark Rutland,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-arm-msm
In-Reply-To: <1478264387-17914-3-git-send-email-srinivas.kandagatla@linaro.org>
Hi,
On Fri, Nov 4, 2016 at 6:29 PM, Srinivas Kandagatla
<srinivas.kandagatla@linaro.org> wrote:
> This patch adds support to msm8996/apq8096 pcie, MSM8996 supports
> Gen 1/2, One lane, 3 pcie root-complex with support to MSI and
> legacy interrupts and it conforms to PCI Express Base 2.1 specification.
>
> This patch adds post_init callback to qcom_pcie_ops, as this is pcie
> pipe clocks are only setup after the phy is powered on.
> It also adds ltssm_enable callback as it is very much different to other
> supported SOCs in the driver.
>
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
> ---
Few minor nits.
> .../devicetree/bindings/pci/qcom,pcie.txt | 68 +++++++-
> drivers/pci/host/pcie-qcom.c | 177 ++++++++++++++++++++-
> 2 files changed, 239 insertions(+), 6 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie.txt b/Documentation/devicetree/bindings/pci/qcom,pcie.txt
> index 4059a6f..4a0538d 100644
> --- a/Documentation/devicetree/bindings/pci/qcom,pcie.txt
> +++ b/Documentation/devicetree/bindings/pci/qcom,pcie.txt
> @@ -7,6 +7,7 @@
> - "qcom,pcie-ipq8064" for ipq8064
> - "qcom,pcie-apq8064" for apq8064
> - "qcom,pcie-apq8084" for apq8084
> + - "qcom,pcie-msm8996" for msm8996 or apq8096
Since this works for both apq8096 and msm8996, compatible -
"qcom,pcie-apq8096" for uniformity ?
[snip]
> @@ -231,3 +242,58 @@
> pinctrl-0 = <&pcie0_pins_default>;
> pinctrl-names = "default";
> };
> +
> +* Example for apq8096:
> +
> + pcie@00608000{
> + compatible = "qcom,pcie-msm8996", "snps,dw-pcie";
this will change accordingly.
> + power-domains = <&gcc PCIE1_GDSC>;
> + bus-range = <0x00 0xff>;
> + num-lanes = <1>;
> +
[snip]
> +
> +static int qcom_pcie_init_v2(struct qcom_pcie *pcie)
> +{
> + struct qcom_pcie_resources_v2 *res = &pcie->res.v2;
> + struct device *dev = pcie->pp.dev;
> + u32 val;
> + int ret = 0;
you don't need to initialize ret here.
> +
> + ret = clk_prepare_enable(res->aux_clk);
> + if (ret) {
> + dev_err(dev, "cannot prepare/enable aux clock\n");
> + return ret;
> + }
[snip]
> @@ -429,6 +571,17 @@ static int qcom_pcie_link_up(struct pcie_port *pp)
> return !!(val & PCI_EXP_LNKSTA_DLLLA);
> }
>
> +static void qcom_pcie_deinit_v2(struct qcom_pcie *pcie)
> +{
> + struct qcom_pcie_resources_v2 *res = &pcie->res.v2;
> +
> + clk_disable_unprepare(res->slave_clk);
> + clk_disable_unprepare(res->master_clk);
> + clk_disable_unprepare(res->cfg_clk);
> + clk_disable_unprepare(res->aux_clk);
> + clk_disable_unprepare(res->pipe_clk);
i am sure, this is not affecting the functionality, but the pipe clock
is enabled after all the clocks.
so it makes sense to disable it in the first place. you can just move
this above slave_clk.
[snip]
> @@ -572,6 +738,7 @@ static const struct of_device_id qcom_pcie_match[] = {
> { .compatible = "qcom,pcie-ipq8064", .data = &ops_v0 },
> { .compatible = "qcom,pcie-apq8064", .data = &ops_v0 },
> { .compatible = "qcom,pcie-apq8084", .data = &ops_v1 },
> + { .compatible = "qcom,pcie-msm8996", .data = &ops_v2 },
this will change according to earlier comment in bindings.
Thanks
Vivek
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply
* Re: [PATCH v3 1/3] i2c: pxa: Add support for the I2C units found in Armada 3700
From: Gregory CLEMENT @ 2016-11-09 10:21 UTC (permalink / raw)
To: Romain Perier
Cc: Mark Rutland, devicetree, Yahuda Yitschak, Omri Itach,
Jason Cooper, Pawel Moll, Ian Campbell, Igal Liberman, Hanna Hawa,
Wolfram Sang, Neta Zur Hershkovits, Nadav Haklai, Rob Herring,
Andrew Lunn, linux-i2c, Kumar Gala, Shadi Ammouri, Marcin Wojtas,
Thomas Petazzoni, linux-arm-kernel, Sebastian Hesselbarth
In-Reply-To: <20161109101349.18722-2-romain.perier@free-electrons.com>
Hi Romain,
You was too fast I didn't have time to commnent about Baruch suggestion.
On mer., nov. 09 2016, Romain Perier <romain.perier@free-electrons.com> wrote:
> The Armada 3700 has two I2C controllers that is compliant with the I2C
> Bus Specificiation 2.1, supports multi-master and different bus speed:
> Standard mode (up to 100 KHz), Fast mode (up to 400 KHz),
> High speed mode (up to 3.4 Mhz).
>
> This IP block has a lot of similarity with the PXA, except some register
> offsets and bitfield. This commits adds a basic support for this I2C
> unit.
>
> Signed-off-by: Romain Perier <romain.perier@free-electrons.com>
> Tested-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> ---
>
> Changes in v3:
> - Replaced the type of hm_mask and fm_mask by unsigned int,
> instead of unsigned long.
[...]
> #define ISR_RWM (1 << 0) /* read/write mode */
> @@ -193,6 +204,8 @@ struct pxa_i2c {
> unsigned char master_code;
> unsigned long rate;
> bool highmode_enter;
> + unsigned int fm_mask;
> + unsigned int hs_mask;
These masks are used with writel and readl which use an u32. So the
better is to use this type.
Gregory
> };
>
> #define _IBMR(i2c) ((i2c)->reg_ibmr)
> @@ -503,8 +516,8 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c)
> writel(i2c->slave_addr, _ISAR(i2c));
>
> /* set control register values */
> - writel(I2C_ICR_INIT | (i2c->fast_mode ? ICR_FM : 0), _ICR(i2c));
> - writel(readl(_ICR(i2c)) | (i2c->high_mode ? ICR_HS : 0), _ICR(i2c));
> + writel(I2C_ICR_INIT | (i2c->fast_mode ? i2c->fm_mask : 0), _ICR(i2c));
> + writel(readl(_ICR(i2c)) | (i2c->high_mode ? i2c->hs_mask : 0), _ICR(i2c));
>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* [PATCH v3 3/3] dt-bindings: i2c: pxa: Update the documentation for the Armada 3700
From: Romain Perier @ 2016-11-09 10:13 UTC (permalink / raw)
To: Wolfram Sang, linux-i2c
Cc: devicetree, Rob Herring, Ian Campbell, Pawel Moll, Mark Rutland,
Kumar Gala, Jason Cooper, Andrew Lunn, Sebastian Hesselbarth,
Gregory Clement, linux-arm-kernel, Thomas Petazzoni, Nadav Haklai,
Omri Itach, Shadi Ammouri, Yahuda Yitschak, Hanna Hawa,
Neta Zur Hershkovits, Igal Liberman, Marcin Wojtas <mw>
In-Reply-To: <20161109101349.18722-1-romain.perier@free-electrons.com>
This commit documents the compatible string to have the compatibility for
the I2C unit found in the Armada 3700.
Signed-off-by: Romain Perier <romain.perier@free-electrons.com>
---
Changes in v2:
- Fixed wrong compatible string, it should be "marvell,armada-3700-i2c"
and not "marvell,armada-3700".
Documentation/devicetree/bindings/i2c/i2c-pxa.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/i2c/i2c-pxa.txt b/Documentation/devicetree/bindings/i2c/i2c-pxa.txt
index 12b78ac..d30f0b1 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-pxa.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-pxa.txt
@@ -7,6 +7,7 @@ Required properties :
compatible processor, e.g. pxa168, pxa910, mmp2, mmp3.
For the pxa2xx/pxa3xx, an additional node "mrvl,pxa-i2c" is required
as shown in the example below.
+ For the Armada 3700, the compatible should be "marvell,armada-3700-i2c".
Recommended properties :
--
2.9.3
^ permalink raw reply related
* [PATCH v3 2/3] arm64: dts: marvell: Add I2C definitions for the Armada 3700
From: Romain Perier @ 2016-11-09 10:13 UTC (permalink / raw)
To: Wolfram Sang, linux-i2c-u79uwXL29TY76Z2rM5mHXA
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Ian Campbell,
Pawel Moll, Mark Rutland, Kumar Gala, Jason Cooper, Andrew Lunn,
Sebastian Hesselbarth, Gregory Clement,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Thomas Petazzoni, Nadav Haklai, Omri Itach, Shadi Ammouri,
Yahuda Yitschak, Hanna Hawa, Neta Zur Hershkovits, Igal Liberman,
Marcin Wojtas <mw>
In-Reply-To: <20161109101349.18722-1-romain.perier-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
The Armada 3700 has two i2c bus interface units, this commit adds the
definitions of the corresponding device nodes. It also enables the node
on the development board for this SoC.
Signed-off-by: Romain Perier <romain.perier-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Acked-by: Gregory CLEMENT <gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
arch/arm64/boot/dts/marvell/armada-3720-db.dts | 4 ++++
arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 18 ++++++++++++++++++
2 files changed, 22 insertions(+)
diff --git a/arch/arm64/boot/dts/marvell/armada-3720-db.dts b/arch/arm64/boot/dts/marvell/armada-3720-db.dts
index 1372e9a6..16d84af 100644
--- a/arch/arm64/boot/dts/marvell/armada-3720-db.dts
+++ b/arch/arm64/boot/dts/marvell/armada-3720-db.dts
@@ -62,6 +62,10 @@
};
};
+&i2c0 {
+ status = "okay";
+};
+
/* CON3 */
&sata {
status = "okay";
diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
index c476253..bf2d73d 100644
--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
@@ -98,6 +98,24 @@
/* 32M internal register @ 0xd000_0000 */
ranges = <0x0 0x0 0xd0000000 0x2000000>;
+ i2c0: i2c@11000 {
+ compatible = "marvell,armada-3700-i2c";
+ reg = <0x11000 0x24>;
+ clocks = <&nb_perih_clk 10>;
+ interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+ mrvl,i2c-fast-mode;
+ status = "disabled";
+ };
+
+ i2c1: i2c@11080 {
+ compatible = "marvell,armada-3700-i2c";
+ reg = <0x11080 0x24>;
+ clocks = <&nb_perih_clk 9>;
+ interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+ mrvl,i2c-fast-mode;
+ status = "disabled";
+ };
+
uart0: serial@12000 {
compatible = "marvell,armada-3700-uart";
reg = <0x12000 0x400>;
--
2.9.3
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v3 1/3] i2c: pxa: Add support for the I2C units found in Armada 3700
From: Romain Perier @ 2016-11-09 10:13 UTC (permalink / raw)
To: Wolfram Sang, linux-i2c-u79uwXL29TY76Z2rM5mHXA
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Ian Campbell,
Pawel Moll, Mark Rutland, Kumar Gala, Jason Cooper, Andrew Lunn,
Sebastian Hesselbarth, Gregory Clement,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Thomas Petazzoni, Nadav Haklai, Omri Itach, Shadi Ammouri,
Yahuda Yitschak, Hanna Hawa, Neta Zur Hershkovits, Igal Liberman,
Marcin Wojtas <mw>
In-Reply-To: <20161109101349.18722-1-romain.perier-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
The Armada 3700 has two I2C controllers that is compliant with the I2C
Bus Specificiation 2.1, supports multi-master and different bus speed:
Standard mode (up to 100 KHz), Fast mode (up to 400 KHz),
High speed mode (up to 3.4 Mhz).
This IP block has a lot of similarity with the PXA, except some register
offsets and bitfield. This commits adds a basic support for this I2C
unit.
Signed-off-by: Romain Perier <romain.perier-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Tested-by: Gregory CLEMENT <gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
Changes in v3:
- Replaced the type of hm_mask and fm_mask by unsigned int,
instead of unsigned long.
drivers/i2c/busses/Kconfig | 2 +-
drivers/i2c/busses/i2c-pxa.c | 25 +++++++++++++++++++++++--
2 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index d252276..2f56a26 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -763,7 +763,7 @@ config I2C_PUV3
config I2C_PXA
tristate "Intel PXA2XX I2C adapter"
- depends on ARCH_PXA || ARCH_MMP || (X86_32 && PCI && OF)
+ depends on ARCH_PXA || ARCH_MMP || ARCH_MVEBU || (X86_32 && PCI && OF)
help
If you have devices in the PXA I2C bus, say yes to this option.
This driver can also be built as a module. If so, the module
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index e28b825..09619db 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -55,6 +55,7 @@ enum pxa_i2c_types {
REGS_PXA3XX,
REGS_CE4100,
REGS_PXA910,
+ REGS_A3700,
};
/*
@@ -91,6 +92,13 @@ static struct pxa_reg_layout pxa_reg_layout[] = {
.ilcr = 0x28,
.iwcr = 0x30,
},
+ [REGS_A3700] = {
+ .ibmr = 0x00,
+ .idbr = 0x04,
+ .icr = 0x08,
+ .isr = 0x0c,
+ .isar = 0x10,
+ },
};
static const struct platform_device_id i2c_pxa_id_table[] = {
@@ -98,6 +106,7 @@ static const struct platform_device_id i2c_pxa_id_table[] = {
{ "pxa3xx-pwri2c", REGS_PXA3XX },
{ "ce4100-i2c", REGS_CE4100 },
{ "pxa910-i2c", REGS_PXA910 },
+ { "armada-3700-i2c", REGS_A3700 },
{ },
};
MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);
@@ -122,7 +131,9 @@ MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);
#define ICR_SADIE (1 << 13) /* slave address detected int enable */
#define ICR_UR (1 << 14) /* unit reset */
#define ICR_FM (1 << 15) /* fast mode */
+#define ICR_BUSMODE_FM (1 << 16) /* shifted fast mode for armada-3700 */
#define ICR_HS (1 << 16) /* High Speed mode */
+#define ICR_BUSMODE_HS (1 << 17) /* shifted high speed mode for armada-3700 */
#define ICR_GPIOEN (1 << 19) /* enable GPIO mode for SCL in HS */
#define ISR_RWM (1 << 0) /* read/write mode */
@@ -193,6 +204,8 @@ struct pxa_i2c {
unsigned char master_code;
unsigned long rate;
bool highmode_enter;
+ unsigned int fm_mask;
+ unsigned int hs_mask;
};
#define _IBMR(i2c) ((i2c)->reg_ibmr)
@@ -503,8 +516,8 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c)
writel(i2c->slave_addr, _ISAR(i2c));
/* set control register values */
- writel(I2C_ICR_INIT | (i2c->fast_mode ? ICR_FM : 0), _ICR(i2c));
- writel(readl(_ICR(i2c)) | (i2c->high_mode ? ICR_HS : 0), _ICR(i2c));
+ writel(I2C_ICR_INIT | (i2c->fast_mode ? i2c->fm_mask : 0), _ICR(i2c));
+ writel(readl(_ICR(i2c)) | (i2c->high_mode ? i2c->hs_mask : 0), _ICR(i2c));
#ifdef CONFIG_I2C_PXA_SLAVE
dev_info(&i2c->adap.dev, "Enabling slave mode\n");
@@ -1137,6 +1150,7 @@ static const struct of_device_id i2c_pxa_dt_ids[] = {
{ .compatible = "mrvl,pxa-i2c", .data = (void *)REGS_PXA2XX },
{ .compatible = "mrvl,pwri2c", .data = (void *)REGS_PXA3XX },
{ .compatible = "mrvl,mmp-twsi", .data = (void *)REGS_PXA910 },
+ { .compatible = "marvell,armada-3700-i2c", .data = (void *)REGS_A3700 },
{}
};
MODULE_DEVICE_TABLE(of, i2c_pxa_dt_ids);
@@ -1158,6 +1172,13 @@ static int i2c_pxa_probe_dt(struct platform_device *pdev, struct pxa_i2c *i2c,
i2c->use_pio = 1;
if (of_get_property(np, "mrvl,i2c-fast-mode", NULL))
i2c->fast_mode = 1;
+ if (of_device_is_compatible(np, "marvell,armada-3700-i2c")) {
+ i2c->fm_mask = ICR_BUSMODE_FM;
+ i2c->hs_mask = ICR_BUSMODE_HS;
+ } else {
+ i2c->fm_mask = ICR_FM;
+ i2c->hs_mask = ICR_HS;
+ }
*i2c_types = (enum pxa_i2c_types)(of_id->data);
--
2.9.3
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v3 0/3] Add basic support for the I2C units of the Armada 3700
From: Romain Perier @ 2016-11-09 10:13 UTC (permalink / raw)
To: Wolfram Sang, linux-i2c
Cc: devicetree, Rob Herring, Ian Campbell, Pawel Moll, Mark Rutland,
Kumar Gala, Jason Cooper, Andrew Lunn, Sebastian Hesselbarth,
Gregory Clement, linux-arm-kernel, Thomas Petazzoni, Nadav Haklai,
Omri Itach, Shadi Ammouri, Yahuda Yitschak, Hanna Hawa,
Neta Zur Hershkovits, Igal Liberman, Marcin Wojtas <mw>
This series add basic support for the I2C bus interface units present
in the Armada 3700 to the pxa-i2c driver. It also add the definitions of
the device nodes to the devicetree at the SoC level and for its official
development board: the Armada 3720 DB.
Romain Perier (3):
i2c: pxa: Add support for the I2C units found in Armada 3700
arm64: dts: marvell: Add I2C definitions for the Armada 3700
dt-bindings: i2c: pxa: Update the documentation for the Armada 3700
Documentation/devicetree/bindings/i2c/i2c-pxa.txt | 1 +
arch/arm64/boot/dts/marvell/armada-3720-db.dts | 4 ++++
arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 18 ++++++++++++++++
drivers/i2c/busses/Kconfig | 2 +-
drivers/i2c/busses/i2c-pxa.c | 25 +++++++++++++++++++++--
5 files changed, 47 insertions(+), 3 deletions(-)
--
2.9.3
^ permalink raw reply
* Re: [PATCH v2 1/3] i2c: pxa: Add support for the I2C units found in Armada 3700
From: Romain Perier @ 2016-11-09 9:55 UTC (permalink / raw)
To: Baruch Siach
Cc: Mark Rutland, Andrew Lunn, Wolfram Sang, Hanna Hawa, Nadav Haklai,
Neta Zur Hershkovits, linux-i2c, Yahuda Yitschak,
linux-arm-kernel, Sebastian Hesselbarth, devicetree, Jason Cooper,
Pawel Moll, Ian Campbell, Omri Itach, Rob Herring,
Gregory Clement, Marcin Wojtas, Igal Liberman, Thomas Petazzoni,
Shadi Ammouri, Kumar Gala
In-Reply-To: <20161109085946.cmd4ltaxpiojq7il@tarshish>
Hi Baruch
Le 09/11/2016 à 09:59, Baruch Siach a écrit :
>> @@ -193,6 +204,8 @@ struct pxa_i2c {
>> unsigned char master_code;
>> unsigned long rate;
>> bool highmode_enter;
>> + unsigned long fm_mask;
>> + unsigned long hs_mask;
>
> Do you really need 64bit for that?
>
> baruch
Mhhh, good point. No I think that I can use an unsigned int.
I will fix it.
Thanks,
Romain
--
Romain Perier, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* Re: [PATCH 1/6] clk: stm32f4: Add PLL_I2S & PLL_SAI for STM32F429/469 boards
From: Gabriel Fernandez @ 2016-11-09 9:51 UTC (permalink / raw)
To: Radosław Pietrzyk
Cc: Mark Rutland, devicetree, Daniel Thompson, Alexandre Torgue,
Arnd Bergmann, Nicolas Pitre, Andrea Merello, linux-kernel,
Michael Turquette, olivier.bideau, Stephen Boyd, Russell King,
amelie.delaunay, Rob Herring, linux-arm-kernel, Maxime Coquelin,
linux-clk, ludovic.barre, kernel
In-Reply-To: <CAFvLkMSUg8=nYY9Zm2Q4ZW=GqUaczK_TA5b5jjb45vYyhoVLZA@mail.gmail.com>
On 11/09/2016 09:10 AM, Radosław Pietrzyk wrote:
> I would expect that VCO clock will force recalculation for all its
> children if I am not mistaken.
Sure
BR
Gabriel.
>
> 2016-11-08 17:19 GMT+01:00 Gabriel Fernandez <gabriel.fernandez@st.com>:
>> On 11/08/2016 09:52 AM, Radosław Pietrzyk wrote:
>>> 2016-11-08 9:35 GMT+01:00 Gabriel Fernandez <gabriel.fernandez@st.com>:
>>>> Hi Radosław
>>>>
>>>> Many thanks for reviewing.
>>>>
>>>> On 11/07/2016 03:57 PM, Radosław Pietrzyk wrote:
>>>>>> +static struct clk_hw *clk_register_pll_div(const char *name,
>>>>>> + const char *parent_name, unsigned long flags,
>>>>>> + void __iomem *reg, u8 shift, u8 width,
>>>>>> + u8 clk_divider_flags, const struct clk_div_table
>>>>>> *table,
>>>>>> + struct clk_hw *pll_hw, spinlock_t *lock)
>>>>>> +{
>>>>>> + struct stm32f4_pll_div *pll_div;
>>>>>> + struct clk_hw *hw;
>>>>>> + struct clk_init_data init;
>>>>>> + int ret;
>>>>>> +
>>>>>> + /* allocate the divider */
>>>>>> + pll_div = kzalloc(sizeof(*pll_div), GFP_KERNEL);
>>>>>> + if (!pll_div)
>>>>>> + return ERR_PTR(-ENOMEM);
>>>>>> +
>>>>>> + init.name = name;
>>>>>> + init.ops = &stm32f4_pll_div_ops;
>>>>>> + init.flags = flags;
>>>>> Maybe it's worth to have CLK_SET_RATE_PARENT here and the VCO clock
>>>>> should have CLK_SET_RATE_GATE flag and we can get rid of custom
>>>>> divider ops.
>>>> I don't want to offer the possibility to change the vco clock through the
>>>> divisor of the pll (only by a boot-loader or by DT).
>>>>
>>>> e.g. if i make a set rate on lcd-tft clock, i don't want to change the
>>>> SAI
>>>> frequencies.
>>>>
>>>> I used same structure for internal divisors of the pll (p, q, r) and for
>>>> post divisors (plli2s-q-div, pllsai-q-div & pllsai-r-div).
>>>> That why the CLK_SET_RATE_PARENT flag is transmit by parameter.
>>>>
>>>> These divisors are similar because we have to switch off the pll before
>>>> changing the rate.
>>>>
>>> But changing pll and lcd dividers only may not be enough for getting
>>> very specific pixelclocks and that might require changing the VCO
>>> frequency itself. The rest of the SAI tree should be recalculated
>>> then.
>> I agree but it seems to be too much complicated to recalculate all PLL
>> divisors if we change the vco clock.
>> You mean to use Clock notifier callback ?
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 6/6] arm: dts: nsp: Add USB nodes to device tree
From: Yendapally Reddy Dhananjaya Reddy @ 2016-11-09 9:33 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Russell King, Ray Jui, Scott Branden,
Jon Mason, Florian Fainelli, Kishon Vijay Abraham I
Cc: bcm-kernel-feedback-list, netdev, devicetree, linux-kernel,
linux-arm-kernel, Yendapally Reddy Dhananjaya Reddy
In-Reply-To: <1478683994-12008-1-git-send-email-yendapally.reddy@broadcom.com>
Add USB nodes to the Northstar plus device tree file
Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com>
---
arch/arm/boot/dts/bcm-nsp.dtsi | 57 ++++++++++++++++++++++++++++++++++++++++
arch/arm/boot/dts/bcm958625k.dts | 16 +++++++++++
2 files changed, 73 insertions(+)
diff --git a/arch/arm/boot/dts/bcm-nsp.dtsi b/arch/arm/boot/dts/bcm-nsp.dtsi
index 7c9e0fa..acdb576 100644
--- a/arch/arm/boot/dts/bcm-nsp.dtsi
+++ b/arch/arm/boot/dts/bcm-nsp.dtsi
@@ -249,6 +249,34 @@
status = "disabled";
};
+ xhci: usb@29000 {
+ compatible = "generic-xhci";
+ reg = <0x29000 0x1000>;
+ interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+ phys = <&usb3_phy>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ehci0: usb@2a000 {
+ compatible = "generic-ehci";
+ reg = <0x2a000 0x100>;
+ interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ ohci0: usb@2b000 {
+ compatible = "generic-ohci";
+ reg = <0x2b000 0x100>;
+ interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ mdio: mdio@32000 {
+ compatible = "brcm,iproc-mdio";
+ reg = <0x32000 0x8>;
+ };
+
rng: rng@33000 {
compatible = "brcm,bcm-nsp-rng";
reg = <0x33000 0x14>;
@@ -319,6 +347,30 @@
"sata2";
};
+ mdio_mux: mdio-mux@3f190 {
+ compatible = "brcm,mdio-mux-nsp";
+ reg = <0x3f190 0x4>,
+ <0x32000 0x4>;
+ reg-names = "bus-ctrl", "mgmt-ctrl";
+ mdio-parent-bus = <&mdio>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mdio@0 {
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ usb3_phy: usb3-phy@10 {
+ compatible = "brcm,nsp-usb3-phy";
+ reg = <0x10>;
+ usb3-ctrl-syscon = <&usb3_ctrl>;
+ #phy-cells = <0>;
+ status = "disabled";
+ };
+ };
+ };
+
pinctrl: pinctrl@3f1c0 {
compatible = "brcm,nsp-pinmux";
reg = <0x3f1c0 0x04>,
@@ -367,6 +419,11 @@
phy-names = "sata-phy";
};
};
+
+ usb3_ctrl: syscon@104408 {
+ compatible = "brcm,nsp-usb3-ctrl", "syscon";
+ reg = <0x104408 0x3fc>;
+ };
};
pcie0: pcie@18012000 {
diff --git a/arch/arm/boot/dts/bcm958625k.dts b/arch/arm/boot/dts/bcm958625k.dts
index 05c5f98..c7303fa 100644
--- a/arch/arm/boot/dts/bcm958625k.dts
+++ b/arch/arm/boot/dts/bcm958625k.dts
@@ -53,6 +53,22 @@
};
};
+&ehci0 {
+ status = "okay";
+};
+
+&ohci0 {
+ status = "okay";
+};
+
+&usb3_phy {
+ status = "okay";
+};
+
+&xhci {
+ status = "okay";
+};
+
&uart0 {
status = "okay";
};
--
2.1.0
^ permalink raw reply related
* [PATCH 5/6] phy: Add USB3 PHY support for Broadcom NSP SoC
From: Yendapally Reddy Dhananjaya Reddy @ 2016-11-09 9:33 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Russell King, Ray Jui, Scott Branden,
Jon Mason, Florian Fainelli, Kishon Vijay Abraham I
Cc: bcm-kernel-feedback-list, netdev, devicetree, linux-kernel,
linux-arm-kernel, Yendapally Reddy Dhananjaya Reddy
In-Reply-To: <1478683994-12008-1-git-send-email-yendapally.reddy@broadcom.com>
This patch adds support for Broadcom NSP USB3 PHY
Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com>
---
drivers/phy/Kconfig | 9 +++
drivers/phy/Makefile | 1 +
drivers/phy/phy-bcm-nsp-usb3.c | 176 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 186 insertions(+)
create mode 100644 drivers/phy/phy-bcm-nsp-usb3.c
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index fe00f91..85cc556 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -489,4 +489,13 @@ config PHY_NS2_PCIE
help
Enable this to support the Broadcom Northstar2 PCIe PHY.
If unsure, say N.
+
+config PHY_NSP_USB3
+ tristate "Broadcom NorthStar plus USB3 PHY driver"
+ depends on OF && (ARCH_BCM_NSP || COMPILE_TEST)
+ select GENERIC_PHY
+ default ARCH_BCM_NSP
+ help
+ Enable this to support the Broadcom Northstar plus USB3 PHY.
+ If unsure, say N.
endmenu
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index a534cf5..ba9b4c0 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -60,3 +60,4 @@ obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o
obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o
obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-$(CONFIG_PHY_NS2_PCIE) += phy-bcm-ns2-pcie.o
+obj-$(CONFIG_PHY_NSP_USB3) += phy-bcm-nsp-usb3.o
diff --git a/drivers/phy/phy-bcm-nsp-usb3.c b/drivers/phy/phy-bcm-nsp-usb3.c
new file mode 100644
index 0000000..0033382
--- /dev/null
+++ b/drivers/phy/phy-bcm-nsp-usb3.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2016 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mdio.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+
+#define NSP_USB3_RST_CTRL_OFFSET 0x3f8
+
+/* mdio reg access */
+#define NSP_USB3_PHY_BASE_ADDR_REG 0x1f
+
+#define NSP_USB3_PHY_PLL30_BLOCK 0x8000
+#define NSP_USB3_PLL_CONTROL 0x01
+#define NSP_USB3_PLLA_CONTROL0 0x0a
+#define NSP_USB3_PLLA_CONTROL1 0x0b
+
+#define NSP_USB3_PHY_TX_PMD_BLOCK 0x8040
+#define NSP_USB3_TX_PMD_CONTROL1 0x01
+
+#define NSP_USB3_PHY_PIPE_BLOCK 0x8060
+#define NSP_USB3_LFPS_CMP 0x02
+#define NSP_USB3_LFPS_DEGLITCH 0x03
+
+struct nsp_usb3_phy {
+ struct regmap *usb3_ctrl;
+ struct phy *phy;
+ struct mdio_device *mdiodev;
+};
+
+static int nsp_usb3_phy_init(struct phy *phy)
+{
+ struct nsp_usb3_phy *iphy = phy_get_drvdata(phy);
+ struct mii_bus *bus = iphy->mdiodev->bus;
+ int addr = iphy->mdiodev->addr;
+ u32 data;
+ int rc;
+
+ rc = regmap_read(iphy->usb3_ctrl, 0, &data);
+ if (rc)
+ return rc;
+ data |= 1;
+ rc = regmap_write(iphy->usb3_ctrl, 0, data);
+ if (rc)
+ return rc;
+
+ rc = regmap_write(iphy->usb3_ctrl, NSP_USB3_RST_CTRL_OFFSET, 1);
+ if (rc)
+ return rc;
+
+ rc = mdiobus_write(bus, addr, NSP_USB3_PHY_BASE_ADDR_REG,
+ NSP_USB3_PHY_PLL30_BLOCK);
+ if (rc)
+ return rc;
+
+ rc = mdiobus_write(bus, addr, NSP_USB3_PLL_CONTROL, 0x1000);
+ if (rc)
+ return rc;
+
+ rc = mdiobus_write(bus, addr, NSP_USB3_PLLA_CONTROL0, 0x6400);
+ if (rc)
+ return rc;
+
+ rc = mdiobus_write(bus, addr, NSP_USB3_PLLA_CONTROL1, 0xc000);
+ if (rc)
+ return rc;
+
+ rc = mdiobus_write(bus, addr, NSP_USB3_PLLA_CONTROL1, 0x8000);
+ if (rc)
+ return rc;
+
+ rc = regmap_write(iphy->usb3_ctrl, NSP_USB3_RST_CTRL_OFFSET, 0);
+ if (rc)
+ return rc;
+
+ rc = mdiobus_write(bus, addr, NSP_USB3_PLL_CONTROL, 0x9000);
+ if (rc)
+ return rc;
+
+ rc = mdiobus_write(bus, addr, NSP_USB3_PHY_BASE_ADDR_REG,
+ NSP_USB3_PHY_PIPE_BLOCK);
+ if (rc)
+ return rc;
+
+ rc = mdiobus_write(bus, addr, NSP_USB3_LFPS_CMP, 0xf30d);
+ if (rc)
+ return rc;
+
+ rc = mdiobus_write(bus, addr, NSP_USB3_LFPS_DEGLITCH, 0x6302);
+ if (rc)
+ return rc;
+
+ rc = mdiobus_write(bus, addr, NSP_USB3_PHY_BASE_ADDR_REG,
+ NSP_USB3_PHY_TX_PMD_BLOCK);
+ if (rc)
+ return rc;
+
+ rc = mdiobus_write(bus, addr, NSP_USB3_TX_PMD_CONTROL1, 0x1003);
+
+ return rc;
+}
+
+static struct phy_ops nsp_usb3_phy_ops = {
+ .init = nsp_usb3_phy_init,
+};
+
+static int nsp_usb3_phy_probe(struct mdio_device *mdiodev)
+{
+ struct device *dev = &mdiodev->dev;
+ struct phy_provider *provider;
+ struct nsp_usb3_phy *iphy;
+
+ iphy = devm_kzalloc(dev, sizeof(*iphy), GFP_KERNEL);
+ if (!iphy)
+ return -ENOMEM;
+ iphy->mdiodev = mdiodev;
+
+ iphy->usb3_ctrl = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "usb3-ctrl-syscon");
+ if (IS_ERR(iphy->usb3_ctrl))
+ return PTR_ERR(iphy->usb3_ctrl);
+
+ iphy->phy = devm_phy_create(dev, dev->of_node, &nsp_usb3_phy_ops);
+ if (IS_ERR(iphy->phy)) {
+ dev_err(dev, "failed to create PHY\n");
+ return PTR_ERR(iphy->phy);
+ }
+
+ phy_set_drvdata(iphy->phy, iphy);
+
+ provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+ if (IS_ERR(provider)) {
+ dev_err(dev, "could not register PHY provider\n");
+ return PTR_ERR(provider);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id nsp_usb3_phy_of_match[] = {
+ {.compatible = "brcm,nsp-usb3-phy",},
+ { /* sentinel */ }
+};
+
+static struct mdio_driver nsp_usb3_phy_driver = {
+ .mdiodrv = {
+ .driver = {
+ .name = "nsp-usb3-phy",
+ .of_match_table = nsp_usb3_phy_of_match,
+ },
+ },
+ .probe = nsp_usb3_phy_probe,
+};
+
+mdio_module_driver(nsp_usb3_phy_driver);
+
+MODULE_DESCRIPTION("Broadcom NSP USB3 PHY driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com");
--
2.1.0
^ permalink raw reply related
* [PATCH 4/6] net: phy: Initialize mdio clock at probe function
From: Yendapally Reddy Dhananjaya Reddy @ 2016-11-09 9:33 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Russell King, Ray Jui, Scott Branden,
Jon Mason, Florian Fainelli, Kishon Vijay Abraham I
Cc: bcm-kernel-feedback-list, netdev, devicetree, linux-kernel,
linux-arm-kernel, Yendapally Reddy Dhananjaya Reddy
In-Reply-To: <1478683994-12008-1-git-send-email-yendapally.reddy@broadcom.com>
Initialize mdio clock divisor in probe function. The ext bus
bit available in the same register will be used by mdio mux
to enable external mdio.
Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com>
---
drivers/net/phy/mdio-bcm-iproc.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/net/phy/mdio-bcm-iproc.c b/drivers/net/phy/mdio-bcm-iproc.c
index c0b4e65..46fe1ae 100644
--- a/drivers/net/phy/mdio-bcm-iproc.c
+++ b/drivers/net/phy/mdio-bcm-iproc.c
@@ -81,8 +81,6 @@ static int iproc_mdio_read(struct mii_bus *bus, int phy_id, int reg)
if (rc)
return rc;
- iproc_mdio_config_clk(priv->base);
-
/* Prepare the read operation */
cmd = (MII_DATA_TA_VAL << MII_DATA_TA_SHIFT) |
(reg << MII_DATA_RA_SHIFT) |
@@ -112,8 +110,6 @@ static int iproc_mdio_write(struct mii_bus *bus, int phy_id,
if (rc)
return rc;
- iproc_mdio_config_clk(priv->base);
-
/* Prepare the write operation */
cmd = (MII_DATA_TA_VAL << MII_DATA_TA_SHIFT) |
(reg << MII_DATA_RA_SHIFT) |
@@ -163,6 +159,8 @@ static int iproc_mdio_probe(struct platform_device *pdev)
bus->read = iproc_mdio_read;
bus->write = iproc_mdio_write;
+ iproc_mdio_config_clk(priv->base);
+
rc = of_mdiobus_register(bus, pdev->dev.of_node);
if (rc) {
dev_err(&pdev->dev, "MDIO bus registration failed\n");
--
2.1.0
^ permalink raw reply related
* [PATCH 3/6] net: mdio-mux: Add MDIO mux driver for NSP SoC
From: Yendapally Reddy Dhananjaya Reddy @ 2016-11-09 9:33 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Russell King, Ray Jui, Scott Branden,
Jon Mason, Florian Fainelli, Kishon Vijay Abraham I
Cc: bcm-kernel-feedback-list, netdev, devicetree, linux-kernel,
linux-arm-kernel, Yendapally Reddy Dhananjaya Reddy
In-Reply-To: <1478683994-12008-1-git-send-email-yendapally.reddy@broadcom.com>
NSP SoC supports the mdio multiplexer which has the bus
selection logic.
This multiplexer has child buses for PCIe, USB. The bus
could be internal or external to SOC where PHYs are attached.
Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com>
---
drivers/net/phy/Kconfig | 9 +++
drivers/net/phy/Makefile | 1 +
drivers/net/phy/mdio-mux-bcm-nsp.c | 121 +++++++++++++++++++++++++++++++++++++
3 files changed, 131 insertions(+)
create mode 100644 drivers/net/phy/mdio-mux-bcm-nsp.c
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 2651c8d..41cc583 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -63,6 +63,15 @@ config MDIO_BUS_MUX_BCM_IPROC
child MDIO bus to a parent bus. Buses could be internal as well as
external and selection logic lies inside the same multiplexer.
+config MDIO_BUS_MUX_BCM_NSP
+ tristate "Broadcom NSP MDIO bus controller"
+ depends on ARCH_BCM_NSP || COMPILE_TEST
+ depends on HAS_IOMEM && OF_MDIO
+ default ARCH_BCM_NSP
+ help
+ This module provides a driver MDIO multiplexing the busses available
+ in the Broadcom NSP SoC.
+
config MDIO_BUS_MUX_GPIO
tristate "GPIO controlled MDIO bus multiplexers"
depends on OF_GPIO && OF_MDIO
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index e58667d..d5969b2 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_MDIO_BUS_MUX) += mdio-mux.o
obj-$(CONFIG_MDIO_BUS_MUX_BCM_IPROC) += mdio-mux-bcm-iproc.o
obj-$(CONFIG_MDIO_BUS_MUX_GPIO) += mdio-mux-gpio.o
obj-$(CONFIG_MDIO_BUS_MUX_MMIOREG) += mdio-mux-mmioreg.o
+obj-$(CONFIG_MDIO_BUS_MUX_BCM_NSP) += mdio-mux-bcm-nsp.o
obj-$(CONFIG_MDIO_CAVIUM) += mdio-cavium.o
obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o
obj-$(CONFIG_MDIO_HISI_FEMAC) += mdio-hisi-femac.o
diff --git a/drivers/net/phy/mdio-mux-bcm-nsp.c b/drivers/net/phy/mdio-mux-bcm-nsp.c
new file mode 100644
index 0000000..75dcb04
--- /dev/null
+++ b/drivers/net/phy/mdio-mux-bcm-nsp.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2016 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation (the "GPL").
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License version 2 (GPLv2) for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/mdio-mux.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+
+#define NSP_MDIO_EXT_BUS_START_ADDR 16
+#define NSP_MDIO_EXT_SELECT_BIT BIT(9)
+
+struct nsp_mdiomux_desc {
+ void __iomem *bus_ctrl;
+ void __iomem *mgmt_ctrl;
+ void *mux_handle;
+};
+
+static int mdio_mux_nsp_switch_fn(int current_child, int desired_child,
+ void *priv)
+{
+ struct nsp_mdiomux_desc *md = priv;
+ u32 data, bus_id;
+
+ /* select internal or external bus */
+ data = readl(md->mgmt_ctrl);
+ if (desired_child == NSP_MDIO_EXT_BUS_START_ADDR)
+ data |= NSP_MDIO_EXT_SELECT_BIT;
+ else
+ data &= ~NSP_MDIO_EXT_SELECT_BIT;
+ writel(data, md->mgmt_ctrl);
+
+ /* select bus number */
+ if (md->bus_ctrl) {
+ bus_id = desired_child & (NSP_MDIO_EXT_BUS_START_ADDR - 1);
+ writel(bus_id, md->bus_ctrl);
+ }
+
+ return 0;
+}
+
+static int mdio_mux_nsp_probe(struct platform_device *pdev)
+{
+ struct nsp_mdiomux_desc *md;
+ struct resource *res;
+ int ret;
+
+ md = devm_kzalloc(&pdev->dev, sizeof(*md), GFP_KERNEL);
+ if (!md)
+ return -ENOMEM;
+
+ /* Bus control is not available in some SoC's */
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bus-ctrl");
+ if (res) {
+ md->bus_ctrl = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(md->bus_ctrl)) {
+ dev_err(&pdev->dev, "failed to ioremap register\n");
+ return PTR_ERR(md->bus_ctrl);
+ }
+ }
+
+ /* Get management control */
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mgmt-ctrl");
+ if (!res)
+ return -EINVAL;
+
+ md->mgmt_ctrl = ioremap(res->start, resource_size(res));
+ if (!md->mgmt_ctrl)
+ return -ENOMEM;
+
+ ret = mdio_mux_init(&pdev->dev, mdio_mux_nsp_switch_fn,
+ &md->mux_handle, md, NULL);
+ if (ret != 0) {
+ iounmap(md->mgmt_ctrl);
+ return ret;
+ }
+
+ pdev->dev.platform_data = md;
+ return 0;
+}
+
+static int mdio_mux_nsp_remove(struct platform_device *pdev)
+{
+ struct nsp_mdiomux_desc *md = dev_get_platdata(&pdev->dev);
+
+ iounmap(md->mgmt_ctrl);
+ mdio_mux_uninit(md->mux_handle);
+ return 0;
+}
+
+static const struct of_device_id mdio_mux_nsp_match[] = {
+ { .compatible = "brcm,mdio-mux-nsp" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mdio_mux_nsp_match);
+
+static struct platform_driver mdio_mux_nsp_driver = {
+ .driver = {
+ .name = "mdio-mux-nsp",
+ .of_match_table = mdio_mux_nsp_match,
+ },
+ .probe = mdio_mux_nsp_probe,
+ .remove = mdio_mux_nsp_remove,
+};
+
+module_platform_driver(mdio_mux_nsp_driver);
+
+MODULE_DESCRIPTION("NSP MDIO Mux Bus Driver");
+MODULE_AUTHOR("Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com");
+MODULE_LICENSE("GPL v2");
--
2.1.0
^ permalink raw reply related
* [PATCH 2/6] dt-bindings: phy: Add documentation for NSP USB3 PHY
From: Yendapally Reddy Dhananjaya Reddy @ 2016-11-09 9:33 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Russell King, Ray Jui, Scott Branden,
Jon Mason, Florian Fainelli, Kishon Vijay Abraham I
Cc: devicetree, netdev, linux-kernel,
Yendapally Reddy Dhananjaya Reddy, bcm-kernel-feedback-list,
linux-arm-kernel
In-Reply-To: <1478683994-12008-1-git-send-email-yendapally.reddy@broadcom.com>
Add documentation for USB3 PHY available in Northstar plus SoC
Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com>
---
.../devicetree/bindings/phy/brcm,nsp-usb3-phy.txt | 39 ++++++++++++++++++++++
1 file changed, 39 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/brcm,nsp-usb3-phy.txt
diff --git a/Documentation/devicetree/bindings/phy/brcm,nsp-usb3-phy.txt b/Documentation/devicetree/bindings/phy/brcm,nsp-usb3-phy.txt
new file mode 100644
index 0000000..30cf4b9
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/brcm,nsp-usb3-phy.txt
@@ -0,0 +1,39 @@
+Broadcom USB3 phy binding northstar plus SoC
+This is a child bus node of "brcm,mdio-mux-nsp" node.
+
+Required mdio bus properties:
+- reg: MDIO Bus number for the MDIO interface
+- #address-cells: must be 1
+- #size-cells: must be 0
+
+Required PHY properties:
+- compatible: should be "brcm,nsp-usb3-phy"
+- reg: Phy address in the MDIO interface
+- usb3-ctrl-syscon: handler of syscon node defining physical address
+ of usb3 control register.
+- #phy-cells: must be 0
+
+Required usb3 control properties:
+- compatible: should be "brcm,nsp-usb3-ctrl"
+- reg: offset and length of the control registers
+
+Example:
+
+ mdio@0 {
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ usb3_phy: usb3-phy@10 {
+ compatible = "brcm,nsp-usb3-phy";
+ reg = <0x10>;
+ usb3-ctrl-syscon = <&usb3_ctrl>;
+ #phy-cells = <0>;
+ status = "disabled";
+ };
+ }
+
+ usb3_ctrl: syscon@104408 {
+ compatible = "brcm,nsp-usb3-ctrl", "syscon";
+ reg = <0x104408 0x3fc>;
+ };
--
2.1.0
^ permalink raw reply related
* [PATCH 1/6] dt-bindings: mdio-mux: Add documentation for mdio mux for NSP SoC
From: Yendapally Reddy Dhananjaya Reddy @ 2016-11-09 9:33 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Russell King, Ray Jui, Scott Branden,
Jon Mason, Florian Fainelli, Kishon Vijay Abraham I
Cc: bcm-kernel-feedback-list, netdev, devicetree, linux-kernel,
linux-arm-kernel, Yendapally Reddy Dhananjaya Reddy
In-Reply-To: <1478683994-12008-1-git-send-email-yendapally.reddy@broadcom.com>
Add documentation for mdio mux available in Broadcom NSP SoC
Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com>
---
.../devicetree/bindings/net/brcm,mdio-mux-nsp.txt | 57 ++++++++++++++++++++++
1 file changed, 57 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/brcm,mdio-mux-nsp.txt
diff --git a/Documentation/devicetree/bindings/net/brcm,mdio-mux-nsp.txt b/Documentation/devicetree/bindings/net/brcm,mdio-mux-nsp.txt
new file mode 100644
index 0000000..b749a2b
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/brcm,mdio-mux-nsp.txt
@@ -0,0 +1,57 @@
+Properties for an MDIO bus multiplexer available in Broadcom NSP SoC.
+
+This MDIO bus multiplexer defines buses that could access the internal
+phys as well as external to SoCs. When child bus is selected, one needs
+to select the below properties to generate desired MDIO transaction on
+appropriate bus.
+
+Required properties in addition to the generic multiplexer properties:
+
+MDIO multiplexer node:
+- compatible: brcm,mdio-mux-iproc.
+- reg: Should contain registers location and length.
+- reg-names: Should contain the resource reg names.
+ - bus-ctrl: mdio bus control register address space required to
+ select the bus master. This property is not required for SoC's
+ that doesn't provide master selection.
+ - mgmt-ctrl: mdio management control register address space
+
+Sub-nodes:
+ Each bus master should be represented as a sub-node.
+
+Sub-nodes required properties:
+- reg: Bus master number. Should be 0x10 to access the external mdio devices.
+- address-cells: should be 1
+- size-cells: should be 0
+
+Every non-ethernet PHY requires a compatible property so that it could be
+probed based on this compatible string.
+
+Additional information regarding generic multiplexer properties can be found
+at- Documentation/devicetree/bindings/net/mdio-mux.txt
+
+example:
+
+ mdio_mux: mdio-mux@3f190 {
+ compatible = "brcm,mdio-mux-nsp";
+ reg = <0x3f190 0x4>,
+ <0x32000 0x4>;
+ reg-names = "bus-ctrl", "mgmt-ctrl";
+ mdio-parent-bus = <&mdio>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mdio@0 {
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ usb3_phy: usb3-phy@10 {
+ compatible = "brcm,nsp-usb3-phy";
+ reg = <0x10>;
+ usb3-ctrl-syscon = <&usb3_ctrl>;
+ #phy-cells = <0>;
+ status = "disabled";
+ };
+ };
+ };
--
2.1.0
^ permalink raw reply related
* [PATCH 0/6] USB support for Broadcom NSP SoC
From: Yendapally Reddy Dhananjaya Reddy @ 2016-11-09 9:33 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Russell King, Ray Jui, Scott Branden,
Jon Mason, Florian Fainelli, Kishon Vijay Abraham I
Cc: bcm-kernel-feedback-list, netdev, devicetree, linux-kernel,
linux-arm-kernel, Yendapally Reddy Dhananjaya Reddy
This patch set contains the usb support for Broadcom NSP SoC.
The usb phy is connected through mdio interface. The mdio interface
can be used to access either internal phys or external phys using a
multiplexer.
The first patch provides the documentation details for mdio-mux and
second patch provides the documentation details for usb3 phy. The third
patch contains the mdio-mux support and fourth patch contains the
changes to the mdio bus driver.
The fifth patch provides the phy driver and sixth patch provides the
enable method for usb.
This patch series has been tested on NSP bcm958625HR board.
This patch series is based on v4.9.0-rc1 and is available from github-
repo: https://github.com/Broadcom/cygnus-linux.git
branch:nsp-usb-v1
Yendapally Reddy Dhananjaya Reddy (6):
dt-bindings: mdio-mux: Add documentation for mdio mux for NSP SoC
dt-bindings: phy: Add documentation for NSP USB3 PHY
net: mdio-mux: Add MDIO mux driver for NSP SoC
net: phy: Initialize mdio clock at probe function
phy: Add USB3 PHY support for Broadcom NSP SoC
arm: dts: nsp: Add USB nodes to device tree
.../devicetree/bindings/net/brcm,mdio-mux-nsp.txt | 57 +++++++
.../devicetree/bindings/phy/brcm,nsp-usb3-phy.txt | 39 +++++
arch/arm/boot/dts/bcm-nsp.dtsi | 57 +++++++
arch/arm/boot/dts/bcm958625k.dts | 16 ++
drivers/net/phy/Kconfig | 9 ++
drivers/net/phy/Makefile | 1 +
drivers/net/phy/mdio-bcm-iproc.c | 6 +-
drivers/net/phy/mdio-mux-bcm-nsp.c | 121 ++++++++++++++
drivers/phy/Kconfig | 9 ++
drivers/phy/Makefile | 1 +
drivers/phy/phy-bcm-nsp-usb3.c | 176 +++++++++++++++++++++
11 files changed, 488 insertions(+), 4 deletions(-)
create mode 100644 Documentation/devicetree/bindings/net/brcm,mdio-mux-nsp.txt
create mode 100644 Documentation/devicetree/bindings/phy/brcm,nsp-usb3-phy.txt
create mode 100644 drivers/net/phy/mdio-mux-bcm-nsp.c
create mode 100644 drivers/phy/phy-bcm-nsp-usb3.c
--
2.1.0
^ permalink raw reply
* Re: [v16, 0/7] Fix eSDHC host version register bug
From: Wolfram Sang @ 2016-11-09 9:18 UTC (permalink / raw)
To: Yangbo Lu
Cc: linux-mmc, ulf.hansson, Scott Wood, Arnd Bergmann, linuxppc-dev,
devicetree, linux-arm-kernel, linux-kernel, linux-clk, linux-i2c,
iommu, netdev, Greg Kroah-Hartman, Mark Rutland, Rob Herring,
Russell King, Jochen Friedrich, Joerg Roedel, Claudiu Manoil,
Bhupesh Sharma, Qiang Zhao, Kumar Gala, Leo Li
In-Reply-To: <1478661252-42439-1-git-send-email-yangbo.lu@nxp.com>
[-- Attachment #1: Type: text/plain, Size: 121 bytes --]
Can you please update your CC list? There is nothing i2c related in this
patch series, so you could drop the i2c-list.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply
* Re: [PATCH v2 1/3] i2c: pxa: Add support for the I2C units found in Armada 3700
From: Baruch Siach @ 2016-11-09 8:59 UTC (permalink / raw)
To: Romain Perier
Cc: Wolfram Sang, linux-i2c-u79uwXL29TY76Z2rM5mHXA, Mark Rutland,
devicetree-u79uwXL29TY76Z2rM5mHXA, Yahuda Yitschak, Jason Cooper,
Pawel Moll, Ian Campbell, Igal Liberman, Hanna Hawa, Omri Itach,
Nadav Haklai, Rob Herring, Andrew Lunn, Neta Zur Hershkovits,
Kumar Gala, Gregory Clement, Shadi Ammouri, Marcin Wojtas,
Thomas Petazzoni, linux-arm-kernel-IAPFreCvJWMP3drIcvDWNA
In-Reply-To: <20161109081431.10115-2-romain.perier-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Hi Romain,
On Wed, Nov 09, 2016 at 09:14:29AM +0100, Romain Perier wrote:
> The Armada 3700 has two I2C controllers that is compliant with the I2C
> Bus Specificiation 2.1, supports multi-master and different bus speed:
> Standard mode (up to 100 KHz), Fast mode (up to 400 KHz),
> High speed mode (up to 3.4 Mhz).
>
> This IP block has a lot of similarity with the PXA, except some register
> offsets and bitfield. This commits adds a basic support for this I2C
> unit.
>
> Signed-off-by: Romain Perier <romain.perier-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> Tested-by: Gregory CLEMENT <gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
[...]
> @@ -122,7 +131,9 @@ MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);
> #define ICR_SADIE (1 << 13) /* slave address detected int enable */
> #define ICR_UR (1 << 14) /* unit reset */
> #define ICR_FM (1 << 15) /* fast mode */
> +#define ICR_BUSMODE_FM (1 << 16) /* shifted fast mode for armada-3700 */
> #define ICR_HS (1 << 16) /* High Speed mode */
> +#define ICR_BUSMODE_HS (1 << 17) /* shifted high speed mode for armada-3700 */
> #define ICR_GPIOEN (1 << 19) /* enable GPIO mode for SCL in HS */
>
> #define ISR_RWM (1 << 0) /* read/write mode */
> @@ -193,6 +204,8 @@ struct pxa_i2c {
> unsigned char master_code;
> unsigned long rate;
> bool highmode_enter;
> + unsigned long fm_mask;
> + unsigned long hs_mask;
Do you really need 64bit for that?
baruch
> };
>
> #define _IBMR(i2c) ((i2c)->reg_ibmr)
> @@ -503,8 +516,8 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c)
> writel(i2c->slave_addr, _ISAR(i2c));
>
> /* set control register values */
> - writel(I2C_ICR_INIT | (i2c->fast_mode ? ICR_FM : 0), _ICR(i2c));
> - writel(readl(_ICR(i2c)) | (i2c->high_mode ? ICR_HS : 0), _ICR(i2c));
> + writel(I2C_ICR_INIT | (i2c->fast_mode ? i2c->fm_mask : 0), _ICR(i2c));
> + writel(readl(_ICR(i2c)) | (i2c->high_mode ? i2c->hs_mask : 0), _ICR(i2c));
>
> #ifdef CONFIG_I2C_PXA_SLAVE
> dev_info(&i2c->adap.dev, "Enabling slave mode\n");
> @@ -1137,6 +1150,7 @@ static const struct of_device_id i2c_pxa_dt_ids[] = {
> { .compatible = "mrvl,pxa-i2c", .data = (void *)REGS_PXA2XX },
> { .compatible = "mrvl,pwri2c", .data = (void *)REGS_PXA3XX },
> { .compatible = "mrvl,mmp-twsi", .data = (void *)REGS_PXA910 },
> + { .compatible = "marvell,armada-3700-i2c", .data = (void *)REGS_A3700 },
> {}
> };
> MODULE_DEVICE_TABLE(of, i2c_pxa_dt_ids);
> @@ -1158,6 +1172,13 @@ static int i2c_pxa_probe_dt(struct platform_device *pdev, struct pxa_i2c *i2c,
> i2c->use_pio = 1;
> if (of_get_property(np, "mrvl,i2c-fast-mode", NULL))
> i2c->fast_mode = 1;
> + if (of_device_is_compatible(np, "marvell,armada-3700-i2c")) {
> + i2c->fm_mask = ICR_BUSMODE_FM;
> + i2c->hs_mask = ICR_BUSMODE_HS;
> + } else {
> + i2c->fm_mask = ICR_FM;
> + i2c->hs_mask = ICR_HS;
> + }
>
> *i2c_types = (enum pxa_i2c_types)(of_id->data);
--
http://baruch.siach.name/blog/ ~. .~ Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
- baruch-NswTu9S1W3P6gbPvEgmw2w@public.gmane.org - tel: +972.52.368.4656, http://www.tkos.co.il -
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v2 1/2] pinctrl: sunxi: Add support for interrupt debouncing
From: Linus Walleij @ 2016-11-09 8:50 UTC (permalink / raw)
To: Maxime Ripard
Cc: Alexandre Courbot,
linux-gpio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Rob Herring,
Chen-Yu Tsai
In-Reply-To: <7dbb47b16d83b843705aa05d4a5f1f7dfdc4e9a3.1478636546.git-series.maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
On Tue, Nov 8, 2016 at 9:24 PM, Maxime Ripard
<maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> The pin controller found in the Allwinner SoCs has support for interrupts
> debouncing.
>
> However, this is not done per-pin, preventing us from using the generic
> pinconf binding for that, but per irq bank, which, depending on the SoC,
> ranges from one to five.
>
> Introduce a device-wide property to deal with this using a microsecond
> resolution. We can re-use the per-pin input-debounce property for that, so
> let's do it!
>
> Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
I like this! Minor nits inline:
> +- clocks: phandle to the clocks feeding the pin controller:
> + - "apb": the gated APB parent clock
> + - "hosc": the high frequency oscillator in the system
> + - "losc": the low frequency oscillator in the system
> +
> +Note: For backward compatibility reasons, the hosc and losc clocks are only
> +required if you need to use the optional input-debounce property. Any new
> +device tree should set them.
> +
> +Optional properties:
> + - input-debounce: Array of debouncing periods in microseconds. One period per
> + irq bank found in the controller
Looks good to me. Cutting the DT people some slack to look at this
before merging.
> +static int sunxi_pinctrl_compute_debounce(struct clk *clk, int freq, int *diff)
> +{
> + unsigned long clock = clk_get_rate(clk);
> + unsigned int best_diff = ~0, best_div;
> + int i;
> +
> + for (i = 0; i < 8; i++) {
> + int cur_diff = abs(freq - (clock >> i));
> +
> + if (cur_diff < best_diff) {
> + best_diff = cur_diff;
> + best_div = i;
> + }
> + }
> +
> + *diff = best_diff;
> + return best_div;
> +}
Kerneldoc or function name should reflect that what this function
does is to find the best divisor.
> +static int sunxi_pinctrl_setup_debounce(struct sunxi_pinctrl *pctl,
> + struct device_node *node)
> +{
> + unsigned int hosc_diff, losc_diff;
> + unsigned int hosc_div, losc_div;
> + struct clk *hosc, *losc;
> + u8 div, src;
> + int i, ret;
> +
> + /* Deal with old DTs that didn't have the oscillators */
> + if (of_count_phandle_with_args(node, "clocks", "#clock-cells") != 3)
> + return 0;
Clever, nice.
> + /* If we don't have any setup, bail out */
> + if (!of_find_property(node, "input-debounce", NULL))
> + return 0;
> +
> + losc = devm_clk_get(pctl->dev, "losc");
> + if (IS_ERR(losc))
> + return PTR_ERR(losc);
> +
> + hosc = devm_clk_get(pctl->dev, "hosc");
> + if (IS_ERR(hosc))
> + return PTR_ERR(hosc);
> +
> + for (i = 0; i < pctl->desc->irq_banks; i++) {
> + unsigned long debounce_freq;
> + u32 debounce;
> +
> + ret = of_property_read_u32_index(node, "input-debounce",
> + i, &debounce);
> + if (ret)
> + return ret;
> +
> + debounce_freq = USEC_PER_SEC / debounce;
Arithmetics! Would you like to use
DIV_ROUND_UP()? or DIV_ROUND_CLOSEST()?
Apart from that I like this patch a lot.
Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v2 3/3] dt-bindings: i2c: pxa: Update the documentation for the Armada 3700
From: Romain Perier @ 2016-11-09 8:14 UTC (permalink / raw)
To: Wolfram Sang, linux-i2c-u79uwXL29TY76Z2rM5mHXA
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Ian Campbell,
Pawel Moll, Mark Rutland, Kumar Gala, Jason Cooper, Andrew Lunn,
Sebastian Hesselbarth, Gregory Clement,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Thomas Petazzoni, Nadav Haklai, Omri Itach, Shadi Ammouri,
Yahuda Yitschak, Hanna Hawa, Neta Zur Hershkovits, Igal Liberman,
Marcin Wojtas <mw>
In-Reply-To: <20161109081431.10115-1-romain.perier-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
This commit documents the compatible string to have the compatibility for
the I2C unit found in the Armada 3700.
Signed-off-by: Romain Perier <romain.perier-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
Changes in v2:
- Fixed wrong compatible string, it should be "marvell,armada-3700-i2c"
and not "marvell,armada-3700".
Documentation/devicetree/bindings/i2c/i2c-pxa.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/i2c/i2c-pxa.txt b/Documentation/devicetree/bindings/i2c/i2c-pxa.txt
index 12b78ac..d30f0b1 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-pxa.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-pxa.txt
@@ -7,6 +7,7 @@ Required properties :
compatible processor, e.g. pxa168, pxa910, mmp2, mmp3.
For the pxa2xx/pxa3xx, an additional node "mrvl,pxa-i2c" is required
as shown in the example below.
+ For the Armada 3700, the compatible should be "marvell,armada-3700-i2c".
Recommended properties :
--
2.9.3
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox